├── .env.development
├── .env.test
├── .erb_lint.yml
├── .gitattributes
├── .github
├── dependabot.yml
└── workflows
│ └── lint-and-test.yml
├── .gitignore
├── .gitmodules
├── .prettierignore
├── .prettierrc
├── .rspec
├── .standard.yml
├── .standard_rubocop_extensions.yml
├── CLAUDE.md
├── Dockerfile.dev
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── Procfile
├── Procfile.dev
├── README.md
├── Rakefile
├── app.json
├── app
├── assets
│ ├── builds
│ │ └── .keep
│ ├── images
│ │ ├── avatar.png
│ │ └── icons
│ │ │ ├── add_fill.svg
│ │ │ ├── alert_fill.svg
│ │ │ ├── arrow_left_fill.svg
│ │ │ ├── caret-left-regular.svg
│ │ │ ├── caret-right-regular.svg
│ │ │ ├── check_circle_fill.svg
│ │ │ ├── check_fill.svg
│ │ │ ├── close_fill.svg
│ │ │ ├── edit_4_fill.svg
│ │ │ ├── edit_4_line.svg
│ │ │ ├── entrance_line.svg
│ │ │ ├── external_link_line.svg
│ │ │ ├── forbid_circle_line.svg
│ │ │ ├── home_4_fill.svg
│ │ │ ├── home_4_line.svg
│ │ │ ├── logo.svg
│ │ │ ├── more_1_fill.svg
│ │ │ ├── notification_fill.svg
│ │ │ ├── notification_line.svg
│ │ │ ├── right_fill.svg
│ │ │ ├── rocket_line.svg
│ │ │ ├── search_fill.svg
│ │ │ ├── search_line.svg
│ │ │ ├── settings_5_line.svg
│ │ │ ├── user_4_fill.svg
│ │ │ └── user_4_line.svg
│ └── stylesheets
│ │ └── application.css
├── components
│ ├── application_component.rb
│ ├── blank_slate_component.html.erb
│ ├── blank_slate_component.rb
│ ├── buttons
│ │ ├── check_suggested_profile_button_component.html.erb
│ │ ├── check_suggested_profile_button_component.rb
│ │ ├── follow_button_component.html.erb
│ │ ├── follow_button_component.rb
│ │ ├── follow_button_with_avatar_component.html.erb
│ │ ├── follow_button_with_avatar_component.rb
│ │ ├── stamp_button_component.html.erb
│ │ └── stamp_button_component.rb
│ ├── cards
│ │ ├── detailed_post_card_component.html.erb
│ │ ├── detailed_post_card_component.rb
│ │ ├── form_errors_card_component.html.erb
│ │ ├── form_errors_card_component.rb
│ │ ├── link_card_component.html.erb
│ │ ├── link_card_component.rb
│ │ ├── notification_card
│ │ │ ├── stamp_notification_component.html.erb
│ │ │ └── stamp_notification_component.rb
│ │ ├── notification_card_component.html.erb
│ │ ├── notification_card_component.rb
│ │ ├── post_card
│ │ │ ├── body_component.html.erb
│ │ │ ├── body_component.rb
│ │ │ ├── footer_component.html.erb
│ │ │ └── footer_component.rb
│ │ ├── post_card_component.html.erb
│ │ ├── post_card_component.rb
│ │ ├── post_nav_link_card_component.html.erb
│ │ ├── post_nav_link_card_component.rb
│ │ ├── profile_card_component.html.erb
│ │ └── profile_card_component.rb
│ ├── containers
│ │ ├── basic_container_component.html.erb
│ │ └── basic_container_component.rb
│ ├── dropdowns
│ │ ├── post_options_dropdown_component.html.erb
│ │ ├── post_options_dropdown_component.rb
│ │ ├── profile_options_dropdown_component.html.erb
│ │ └── profile_options_dropdown_component.rb
│ ├── entry_headers
│ │ ├── basic_entry_header_component.html.erb
│ │ └── basic_entry_header_component.rb
│ ├── footers
│ │ ├── basic_footer_component.html.erb
│ │ └── basic_footer_component.rb
│ ├── forms
│ │ ├── keyword_search_form_component.html.erb
│ │ ├── keyword_search_form_component.rb
│ │ ├── post_form_component.html.erb
│ │ └── post_form_component.rb
│ ├── icons
│ │ ├── logo_icon_component.html.erb
│ │ ├── logo_icon_component.rb
│ │ ├── navbar_menu_icon_component.html.erb
│ │ ├── navbar_menu_icon_component.rb
│ │ ├── stamped_icon_component.rb
│ │ └── unstamped_icon_component.rb
│ ├── images
│ │ ├── avatar_image_component.html.erb
│ │ ├── avatar_image_component.rb
│ │ ├── profile_avatar_image_component.html.erb
│ │ └── profile_avatar_image_component.rb
│ ├── layouts
│ │ ├── basic_layout_component.html.erb
│ │ ├── basic_layout_component.rb
│ │ ├── simple_layout_component.html.erb
│ │ └── simple_layout_component.rb
│ ├── links
│ │ ├── post_nav_link_component.html.erb
│ │ └── post_nav_link_component.rb
│ ├── lists
│ │ ├── post_card_list_component.html.erb
│ │ └── post_card_list_component.rb
│ ├── modals
│ │ ├── base
│ │ │ ├── modal_box_component.html.erb
│ │ │ ├── modal_box_component.rb
│ │ │ ├── modal_component.html.erb
│ │ │ └── modal_component.rb
│ │ ├── post_form_modal_component.html.erb
│ │ └── post_form_modal_component.rb
│ ├── navbar_menu_component.html.erb
│ ├── navbar_menu_component.rb
│ ├── navbars
│ │ ├── bottom_navbar_component.html.erb
│ │ ├── bottom_navbar_component.rb
│ │ ├── top_navbar_component.html.erb
│ │ └── top_navbar_component.rb
│ ├── paginations
│ │ ├── pagination_component.erb
│ │ └── pagination_component.rb
│ ├── tabs
│ │ ├── timeline_tabs_component.html.erb
│ │ └── timeline_tabs_component.rb
│ └── toasts
│ │ ├── flash_toast_component.html.erb
│ │ └── flash_toast_component.rb
├── controllers
│ ├── accounts
│ │ ├── create_controller.rb
│ │ └── new_controller.rb
│ ├── api
│ │ └── v1
│ │ │ ├── README.md
│ │ │ ├── application_controller.rb
│ │ │ ├── follows
│ │ │ ├── create_controller.rb
│ │ │ └── destroy_controller.rb
│ │ │ ├── internal
│ │ │ ├── accounts
│ │ │ │ └── create_controller.rb
│ │ │ ├── application_controller.rb
│ │ │ ├── email_confirmations
│ │ │ │ ├── challenges
│ │ │ │ │ └── create_controller.rb
│ │ │ │ ├── create_controller.rb
│ │ │ │ └── show_controller.rb
│ │ │ ├── passwords
│ │ │ │ └── update_controller.rb
│ │ │ ├── posts
│ │ │ │ └── show_controller.rb
│ │ │ ├── profiles
│ │ │ │ └── posts
│ │ │ │ │ └── index_controller.rb
│ │ │ └── sessions
│ │ │ │ └── create_controller.rb
│ │ │ ├── notifications
│ │ │ └── index_controller.rb
│ │ │ ├── posts
│ │ │ ├── create_controller.rb
│ │ │ ├── destroy_controller.rb
│ │ │ └── show_controller.rb
│ │ │ ├── profiles
│ │ │ ├── me
│ │ │ │ ├── show_controller.rb
│ │ │ │ └── update_controller.rb
│ │ │ └── posts
│ │ │ │ └── index_controller.rb
│ │ │ ├── stamps
│ │ │ ├── create_controller.rb
│ │ │ └── destroy_controller.rb
│ │ │ ├── suggested_profiles
│ │ │ ├── checks
│ │ │ │ └── create_controller.rb
│ │ │ └── index_controller.rb
│ │ │ ├── timeline
│ │ │ └── show_controller.rb
│ │ │ └── users
│ │ │ └── me
│ │ │ ├── show_controller.rb
│ │ │ └── update_controller.rb
│ ├── application_controller.rb
│ ├── checks
│ │ └── create_controller.rb
│ ├── communities
│ │ └── show_controller.rb
│ ├── controller_concerns
│ │ ├── api
│ │ │ ├── authenticatable.rb
│ │ │ └── v1
│ │ │ │ └── form_errorable.rb
│ │ ├── authenticatable.rb
│ │ ├── authorizable.rb
│ │ ├── email_confirmation_findable.rb
│ │ └── localizable.rb
│ ├── email_confirmations
│ │ ├── create_controller.rb
│ │ └── new_controller.rb
│ ├── followees
│ │ └── index_controller.rb
│ ├── follows
│ │ ├── create_controller.rb
│ │ └── destroy_controller.rb
│ ├── home
│ │ └── show_controller.rb
│ ├── links
│ │ ├── create_controller.rb
│ │ └── new_controller.rb
│ ├── manifests
│ │ └── show_controller.rb
│ ├── notifications
│ │ └── index_controller.rb
│ ├── password_resets
│ │ ├── create_controller.rb
│ │ └── new_controller.rb
│ ├── passwords
│ │ ├── edit_controller.rb
│ │ └── update_controller.rb
│ ├── posts
│ │ ├── create_controller.rb
│ │ ├── destroy_controller.rb
│ │ ├── new_controller.rb
│ │ └── show_controller.rb
│ ├── privacies
│ │ └── show_controller.rb
│ ├── profiles
│ │ ├── atom
│ │ │ └── show_controller.rb
│ │ └── show_controller.rb
│ ├── public
│ │ └── show_controller.rb
│ ├── search
│ │ ├── profiles
│ │ │ └── index_controller.rb
│ │ └── show_controller.rb
│ ├── sessions
│ │ ├── create_controller.rb
│ │ ├── destroy_controller.rb
│ │ └── new_controller.rb
│ ├── settings
│ │ ├── emails
│ │ │ ├── show_controller.rb
│ │ │ └── update_controller.rb
│ │ ├── index_controller.rb
│ │ ├── profiles
│ │ │ ├── show_controller.rb
│ │ │ └── update_controller.rb
│ │ └── users
│ │ │ ├── show_controller.rb
│ │ │ └── update_controller.rb
│ ├── sign_up
│ │ ├── create_controller.rb
│ │ └── new_controller.rb
│ ├── stamps
│ │ ├── create_controller.rb
│ │ └── destroy_controller.rb
│ ├── terms
│ │ └── show_controller.rb
│ └── welcome
│ │ └── show_controller.rb
├── forms
│ ├── account_form.rb
│ ├── application_form.rb
│ ├── delete_post_form.rb
│ ├── discard_post_form.rb
│ ├── email_confirmation_challenge_form.rb
│ ├── email_confirmation_form.rb
│ ├── email_update_form.rb
│ ├── follow_form.rb
│ ├── form_concerns
│ │ └── password_validatable.rb
│ ├── keyword_search_form.rb
│ ├── link_data_fetcher_form.rb
│ ├── link_form.rb
│ ├── password_reset_form.rb
│ ├── post_form.rb
│ ├── profile_form.rb
│ ├── session_form.rb
│ ├── stamp_form.rb
│ ├── suggested_follow_form.rb
│ └── user_form.rb
├── helpers
│ ├── application_helper.rb
│ ├── flash_toast_helper.rb
│ ├── language_helper.rb
│ ├── profiles_helper.rb
│ ├── text_helper.rb
│ └── time_helper.rb
├── javascript
│ ├── application.ts
│ ├── controllers
│ │ ├── autosize-controller.ts
│ │ ├── character-counter-controller.ts
│ │ ├── clipboard-controller.ts
│ │ ├── dropdown-controller.ts
│ │ ├── flash-toast-controller.ts
│ │ ├── flash-toast-dispatch-controller.ts
│ │ ├── link-card-form-controller.ts
│ │ └── modal-controller.ts
│ └── utils
│ │ ├── event-dispatcher.ts
│ │ └── fetcher.ts
├── jobs
│ ├── add_followed_profile_posts_to_timeline_job.rb
│ ├── add_post_to_timeline_job.rb
│ ├── application_job.rb
│ ├── create_suggested_follows_job.rb
│ ├── delete_post_job.rb
│ ├── fanout_post_job.rb
│ └── remove_followed_profile_posts_from_timeline_job.rb
├── lib
│ └── mewst
│ │ └── test
│ │ └── resource_helpers.rb
├── mailers
│ ├── application_mailer.rb
│ └── email_confirmation_mailer.rb
├── models
│ ├── actor.rb
│ ├── application_record.rb
│ ├── email_confirmation.rb
│ ├── email_confirmation_event.rb
│ ├── follow.rb
│ ├── follow_checker.rb
│ ├── gravatar.rb
│ ├── home_timeline_post.rb
│ ├── link.rb
│ ├── link_data_fetcher.rb
│ ├── locale.rb
│ ├── model_concerns
│ │ └── notifiable.rb
│ ├── notifiable_type.rb
│ ├── notification.rb
│ ├── oauth_access_token.rb
│ ├── oauth_application.rb
│ ├── page_info.rb
│ ├── post.rb
│ ├── post_link.rb
│ ├── profile.rb
│ ├── profile
│ │ ├── home_timeline.rb
│ │ └── postability.rb
│ ├── profile_avatar_kind.rb
│ ├── profile_owner_type.rb
│ ├── session.rb
│ ├── sign_up_stopper.rb
│ ├── stamp.rb
│ ├── stamp_checker.rb
│ ├── suggested_follow.rb
│ ├── url.rb
│ ├── user.rb
│ ├── user_profile.rb
│ └── v1
│ │ └── response_error_code.rb
├── policies
│ ├── application_policy.rb
│ ├── post_policy.rb
│ └── profile_policy.rb
├── resources
│ ├── concerns
│ │ └── resource_concerns
│ │ │ └── error_responsable.rb
│ └── v1
│ │ ├── account_resource.rb
│ │ ├── application_resource.rb
│ │ ├── email_confirmation_resource.rb
│ │ ├── follow_form_error_resource.rb
│ │ ├── form_error_resource.rb
│ │ ├── notification_resource.rb
│ │ ├── post_form_error_resource.rb
│ │ ├── post_resource.rb
│ │ ├── profile_resource.rb
│ │ ├── response_error_resource.rb
│ │ ├── session_form_error_resource.rb
│ │ ├── stamp_form_error_resource.rb
│ │ ├── stamp_notification_item_resource.rb
│ │ ├── suggested_follow_form_error_resource.rb
│ │ ├── unfollow_form_error_resource.rb
│ │ ├── user_resource.rb
│ │ └── via_resource.rb
├── serializers
│ └── v1
│ │ ├── account_serializer.rb
│ │ ├── application_serializer.rb
│ │ ├── email_confirmation_serializer.rb
│ │ ├── form_error_serializer.rb
│ │ ├── notification_serializer.rb
│ │ ├── oauth_access_token_serializer.rb
│ │ ├── page_info_serializer.rb
│ │ ├── post_serializer.rb
│ │ ├── profile_serializer.rb
│ │ ├── response_error_serializer.rb
│ │ ├── stamp_notification_item_serializer.rb
│ │ ├── user_serializer.rb
│ │ └── via_serializer.rb
├── use_cases
│ ├── add_followed_profile_posts_to_timeline_use_case.rb
│ ├── application_use_case.rb
│ ├── check_suggested_follow_use_case.rb
│ ├── confirm_email_use_case.rb
│ ├── create_account_use_case.rb
│ ├── create_email_confirmation_use_case.rb
│ ├── create_link_use_case.rb
│ ├── create_post_use_case.rb
│ ├── create_session_use_case.rb
│ ├── create_stamp_use_case.rb
│ ├── create_suggested_follows_use_case.rb
│ ├── delete_post_use_case.rb
│ ├── delete_stamp_use_case.rb
│ ├── discard_post_use_case.rb
│ ├── fanout_post_use_case.rb
│ ├── follow_profile_use_case.rb
│ ├── remove_followed_profile_posts_from_timeline_use_case.rb
│ ├── unfollow_profile_use_case.rb
│ ├── update_password_use_case.rb
│ ├── update_profile_use_case.rb
│ └── update_user_use_case.rb
├── validators
│ ├── unreserved_atname_validator.rb
│ └── url_validator.rb
└── views
│ ├── accounts
│ └── new
│ │ └── call.html.erb
│ ├── checks
│ └── create
│ │ └── call.html.erb
│ ├── email_confirmation_mailer
│ ├── email_confirmation.en.html.erb
│ └── email_confirmation.ja.html.erb
│ ├── email_confirmations
│ └── new
│ │ └── call.html.erb
│ ├── followees
│ └── index
│ │ └── call.html.erb
│ ├── follows
│ └── create
│ │ └── call.html.erb
│ ├── home
│ └── show
│ │ └── call.html.erb
│ ├── layouts
│ ├── application.html.erb
│ ├── mailer.html.erb
│ └── mailer.text.erb
│ ├── links
│ ├── create
│ │ └── call.html.erb
│ └── new
│ │ └── call.html.erb
│ ├── manifests
│ └── show
│ │ └── call.json.erb
│ ├── notifications
│ └── index
│ │ └── call.html.erb
│ ├── password_resets
│ └── new
│ │ └── call.html.erb
│ ├── passwords
│ └── edit
│ │ └── call.html.erb
│ ├── posts
│ ├── create
│ │ └── call.html.erb
│ ├── new
│ │ └── call.html.erb
│ └── show
│ │ └── call.html.erb
│ ├── profiles
│ ├── atom
│ │ └── show
│ │ │ └── call.atom.builder
│ └── show
│ │ └── call.html.erb
│ ├── public
│ └── show
│ │ └── call.html.erb
│ ├── search
│ ├── profiles
│ │ └── index
│ │ │ └── call.html.erb
│ └── show
│ │ └── call.html.erb
│ ├── sessions
│ └── new
│ │ └── call.html.erb
│ ├── settings
│ ├── emails
│ │ └── show
│ │ │ └── call.html.erb
│ ├── index
│ │ └── call.html.erb
│ ├── profiles
│ │ └── show
│ │ │ └── call.html.erb
│ └── users
│ │ └── show
│ │ └── call.html.erb
│ ├── sign_up
│ └── new
│ │ └── call.html.erb
│ ├── stamps
│ └── create
│ │ └── call.html.erb
│ └── welcome
│ └── show
│ └── call.html.erb
├── bin
├── check
├── dev
├── erb_lint
├── erblint
├── good_job
├── puma
├── pumactl
├── rails
├── rake
├── rspec
├── setup
├── srb
├── srb-rbi
├── standardrb
└── tapioca
├── config.ru
├── config
├── application.rb
├── boot.rb
├── credentials.yml.enc
├── database.yml
├── environment.rb
├── environments
│ ├── development.rb
│ ├── production.rb
│ └── test.rb
├── initializers
│ ├── alba.rb
│ ├── assets.rb
│ ├── content_security_policy.rb
│ ├── doorkeeper.rb
│ ├── enable_yjit.rb
│ ├── filter_parameter_logging.rb
│ ├── good_job.rb
│ ├── inflections.rb
│ ├── inline_svg.rb
│ ├── not_nil.rb
│ ├── permissions_policy.rb
│ ├── rails_live_reload.rb
│ ├── resend.rb
│ ├── sentry.rb
│ ├── session_store.rb
│ ├── sorbet.rb
│ ├── strong_migrations.rb
│ ├── time_formats.rb
│ └── types.rb
├── locales
│ ├── actionmailer.en.yml
│ ├── actionmailer.ja.yml
│ ├── activerecord.en.yml
│ ├── activerecord.ja.yml
│ ├── doorkeeper.en.yml
│ ├── errors.en.yml
│ ├── errors.ja.yml
│ ├── forms.en.yml
│ ├── forms.ja.yml
│ ├── messages.en.yml
│ ├── messages.ja.yml
│ ├── meta.en.yml
│ ├── meta.ja.yml
│ ├── nouns.en.yml
│ ├── nouns.ja.yml
│ ├── verbs.en.yml
│ └── verbs.ja.yml
├── mewst.yml
├── puma.rb
└── routes.rb
├── db
├── migrate
│ ├── 20220000000001_initial_setup.rb
│ ├── 20221119004702_create_initial_tables.rb
│ ├── 20230830155958_create_good_jobs.rb
│ ├── 20231015050126_add_time_zone_to_users.rb
│ ├── 20231025165318_add_discarded_at_to_posts_and_profiles.rb
│ ├── 20231028081207_add_notification_tables.rb
│ ├── 20231107174301_rename_comment_to_content_on_posts.rb
│ ├── 20231112022226_add_last_post_at_to_profiles.rb
│ ├── 20231112024413_create_suggested_follows.rb
│ ├── 20231113161740_add_via_id_to_posts.rb
│ ├── 20231113162310_add_validation_via_id_to_posts.rb
│ ├── 20231115145714_add_null_false_to_oauth_application_id_on_posts.rb
│ ├── 20231115172238_change_email_columns_to_citext.rb
│ ├── 20231216042900_drop_follow_notifications.rb
│ ├── 20240115144958_create_good_job_settings.rb
│ ├── 20240115144959_create_index_good_jobs_jobs_on_priority_created_at_when_unfinished.rb
│ ├── 20240115144960_create_good_job_batches.rb
│ ├── 20240115144961_create_good_job_executions.rb
│ ├── 20240115144962_create_good_jobs_error_event.rb
│ ├── 20240115144963_recreate_good_job_cron_indexes_with_conditional.rb
│ ├── 20240115144964_create_good_job_labels.rb
│ ├── 20240115144965_create_good_job_labels_index.rb
│ ├── 20240115144966_remove_good_job_active_id_index.rb
│ ├── 20240304164746_update_schema_202403.rb
│ ├── 20240324094358_create_home_timeline_posts.rb
│ ├── 20240403174827_create_sessions.rb
│ ├── 20240404162020_remove_sign_in_columns_on_users.rb
│ ├── 20240414152059_remove_stamps_count_on_posts.rb
│ ├── 20240414155158_create_links.rb
│ ├── 20240414155325_create_post_links.rb
│ ├── 20240422190022_fix_notifications_for_delegated_type.rb
│ └── 20240427202315_add_gravatar_url_to_profiles.rb
├── seeds.rb
└── structure.sql
├── docker-compose.yml
├── fixtures
└── vcr_cassettes
│ └── link_data_fetcher
│ ├── redirect_other_domain.yml
│ ├── redirect_www_to_no_www.yml
│ ├── threads_url.yml
│ ├── valid.yml
│ ├── without_canonical.yml
│ ├── without_og_image.yml
│ ├── without_title.yml
│ └── youtube_short_url.yml
├── lib
├── mewst
│ └── ui
│ │ ├── base.rb
│ │ ├── button.html.erb
│ │ ├── button.rb
│ │ ├── card.html.erb
│ │ ├── card.rb
│ │ ├── card
│ │ ├── body.html.erb
│ │ └── body.rb
│ │ ├── dropdown.html.erb
│ │ ├── dropdown.rb
│ │ ├── dropdown
│ │ ├── button.html.erb
│ │ ├── button.rb
│ │ ├── item.html.erb
│ │ ├── item.rb
│ │ ├── list.html.erb
│ │ └── list.rb
│ │ ├── icon.html.erb
│ │ ├── icon.rb
│ │ ├── tabs.html.erb
│ │ ├── tabs.rb
│ │ └── tabs
│ │ ├── item.html.erb
│ │ └── item.rb
└── tasks
│ ├── sorbet.rake
│ └── suggested_follow.rake
├── openapi
└── v1.yaml
├── package.json
├── public
├── 404.html
├── 422.html
├── 500.html
├── apple-touch-icon.png
├── favicon.ico
├── icon-192.png
├── icon-512.png
├── icon.svg
├── maintenance.html
├── og-image.png
└── robots.txt
├── sorbet
├── config
├── rbi
│ ├── annotations
│ │ ├── .gitattributes
│ │ ├── actionmailer.rbi
│ │ ├── actionpack.rbi
│ │ ├── actionview.rbi
│ │ ├── activejob.rbi
│ │ ├── activemodel.rbi
│ │ ├── activerecord.rbi
│ │ ├── activesupport.rbi
│ │ ├── faraday.rbi
│ │ ├── globalid.rbi
│ │ ├── minitest.rbi
│ │ ├── pundit.rbi
│ │ ├── railties.rbi
│ │ └── rainbow.rbi
│ ├── dsl
│ │ ├── .gitattributes
│ │ ├── abstract_controller
│ │ │ ├── caching.rbi
│ │ │ ├── caching
│ │ │ │ └── fragments.rbi
│ │ │ ├── callbacks.rbi
│ │ │ ├── helpers.rbi
│ │ │ ├── rendering.rbi
│ │ │ └── url_for.rbi
│ │ ├── account_form.rbi
│ │ ├── accounts
│ │ │ ├── create_controller.rbi
│ │ │ └── new_controller.rbi
│ │ ├── action_controller
│ │ │ ├── api_rendering.rbi
│ │ │ ├── caching.rbi
│ │ │ ├── conditional_get.rbi
│ │ │ ├── content_security_policy.rbi
│ │ │ ├── data_streaming.rbi
│ │ │ ├── etag_with_flash.rbi
│ │ │ ├── etag_with_template_digest.rbi
│ │ │ ├── flash.rbi
│ │ │ ├── form_builder.rbi
│ │ │ ├── helpers.rbi
│ │ │ ├── params_wrapper.rbi
│ │ │ ├── redirecting.rbi
│ │ │ ├── renderers.rbi
│ │ │ ├── renderers
│ │ │ │ └── all.rbi
│ │ │ ├── request_forgery_protection.rbi
│ │ │ ├── rescue.rbi
│ │ │ ├── test_case
│ │ │ │ └── behavior.rbi
│ │ │ └── url_for.rbi
│ │ ├── action_dispatch
│ │ │ ├── assertions.rbi
│ │ │ ├── integration_test.rbi
│ │ │ └── routing
│ │ │ │ ├── route_set
│ │ │ │ └── mounted_helpers.rbi
│ │ │ │ └── url_for.rbi
│ │ ├── action_mailer
│ │ │ ├── callbacks.rbi
│ │ │ ├── delivery_methods.rbi
│ │ │ ├── form_builder.rbi
│ │ │ ├── mail_delivery_job.rbi
│ │ │ ├── queued_delivery.rbi
│ │ │ ├── rescuable.rbi
│ │ │ └── test_case
│ │ │ │ └── behavior.rbi
│ │ ├── action_view
│ │ │ ├── helpers.rbi
│ │ │ ├── helpers
│ │ │ │ ├── form_helper.rbi
│ │ │ │ ├── form_tag_helper.rbi
│ │ │ │ └── text_helper.rbi
│ │ │ ├── layouts.rbi
│ │ │ └── rendering.rbi
│ │ ├── active_job
│ │ │ ├── callbacks.rbi
│ │ │ ├── exceptions.rbi
│ │ │ ├── execution.rbi
│ │ │ ├── logging.rbi
│ │ │ ├── queue_adapter.rbi
│ │ │ ├── queue_name.rbi
│ │ │ ├── queue_priority.rbi
│ │ │ └── test_helper
│ │ │ │ └── test_queue_adapter.rbi
│ │ ├── active_model
│ │ │ ├── api.rbi
│ │ │ ├── attribute_methods.rbi
│ │ │ ├── attributes.rbi
│ │ │ ├── conversion.rbi
│ │ │ ├── dirty.rbi
│ │ │ ├── model.rbi
│ │ │ ├── serializers
│ │ │ │ └── json.rbi
│ │ │ ├── validations.rbi
│ │ │ └── validations
│ │ │ │ └── callbacks.rbi
│ │ ├── active_record
│ │ │ ├── attribute_methods.rbi
│ │ │ ├── attribute_methods
│ │ │ │ ├── dirty.rbi
│ │ │ │ ├── serialization.rbi
│ │ │ │ └── time_zone_conversion.rbi
│ │ │ ├── attributes.rbi
│ │ │ ├── callbacks.rbi
│ │ │ ├── core.rbi
│ │ │ ├── counter_cache.rbi
│ │ │ ├── encryption
│ │ │ │ └── encryptable_record.rbi
│ │ │ ├── inheritance.rbi
│ │ │ ├── integration.rbi
│ │ │ ├── locking
│ │ │ │ └── optimistic.rbi
│ │ │ ├── model_schema.rbi
│ │ │ ├── nested_attributes.rbi
│ │ │ ├── normalization.rbi
│ │ │ ├── readonly_attributes.rbi
│ │ │ ├── reflection.rbi
│ │ │ ├── scoping.rbi
│ │ │ ├── scoping
│ │ │ │ └── default.rbi
│ │ │ ├── secure_password.rbi
│ │ │ ├── serialization.rbi
│ │ │ ├── signed_id.rbi
│ │ │ ├── timestamp.rbi
│ │ │ ├── token_for.rbi
│ │ │ └── validations.rbi
│ │ ├── active_support
│ │ │ ├── actionable_error.rbi
│ │ │ ├── callbacks.rbi
│ │ │ ├── rescuable.rbi
│ │ │ └── testing
│ │ │ │ └── file_fixtures.rbi
│ │ ├── actor.rbi
│ │ ├── add_followed_profile_posts_to_timeline_job.rbi
│ │ ├── add_post_to_timeline_job.rbi
│ │ ├── api
│ │ │ └── v1
│ │ │ │ ├── application_controller.rbi
│ │ │ │ └── internal
│ │ │ │ └── application_controller.rbi
│ │ ├── application_component.rbi
│ │ ├── application_controller.rbi
│ │ ├── application_mailer.rbi
│ │ ├── checks
│ │ │ └── create_controller.rbi
│ │ ├── create_suggested_follows_job.rbi
│ │ ├── delete_post_form.rbi
│ │ ├── delete_post_job.rbi
│ │ ├── discard
│ │ │ └── model.rbi
│ │ ├── discard_post_form.rbi
│ │ ├── doorkeeper
│ │ │ ├── access_grant.rbi
│ │ │ ├── access_grant_mixin.rbi
│ │ │ ├── access_token.rbi
│ │ │ ├── access_token_mixin.rbi
│ │ │ ├── application.rbi
│ │ │ ├── application_controller.rbi
│ │ │ ├── application_metal_controller.rbi
│ │ │ └── application_mixin.rbi
│ │ ├── email_confirmation.rbi
│ │ ├── email_confirmation_challenge_form.rbi
│ │ ├── email_confirmation_form.rbi
│ │ ├── email_confirmation_mailer.rbi
│ │ ├── email_confirmations
│ │ │ ├── create_controller.rbi
│ │ │ └── new_controller.rbi
│ │ ├── email_update_form.rbi
│ │ ├── fanout_post_job.rbi
│ │ ├── follow.rbi
│ │ ├── follow_form.rbi
│ │ ├── followees
│ │ │ └── index_controller.rbi
│ │ ├── follows
│ │ │ ├── create_controller.rbi
│ │ │ └── destroy_controller.rbi
│ │ ├── generated_path_helpers_module.rbi
│ │ ├── generated_url_helpers_module.rbi
│ │ ├── good_job
│ │ │ ├── active_job_extensions
│ │ │ │ ├── concurrency.rbi
│ │ │ │ ├── labels.rbi
│ │ │ │ └── notify_options.rbi
│ │ │ ├── advisory_lockable.rbi
│ │ │ ├── application_controller.rbi
│ │ │ ├── base_execution.rbi
│ │ │ ├── batch_record.rbi
│ │ │ ├── discrete_execution.rbi
│ │ │ ├── execution.rbi
│ │ │ ├── frontends_controller.rbi
│ │ │ ├── job.rbi
│ │ │ ├── process.rbi
│ │ │ └── setting.rbi
│ │ ├── home
│ │ │ └── show_controller.rbi
│ │ ├── home_timeline_post.rbi
│ │ ├── keyword_search_form.rbi
│ │ ├── link.rbi
│ │ ├── link_data_fetcher_form.rbi
│ │ ├── link_form.rbi
│ │ ├── links
│ │ │ ├── create_controller.rbi
│ │ │ └── new_controller.rbi
│ │ ├── mewst
│ │ │ └── ui
│ │ │ │ └── base.rbi
│ │ ├── notification.rbi
│ │ ├── notifications
│ │ │ └── index_controller.rbi
│ │ ├── oauth_access_token.rbi
│ │ ├── oauth_application.rbi
│ │ ├── password_reset_form.rbi
│ │ ├── password_resets
│ │ │ ├── create_controller.rbi
│ │ │ └── new_controller.rbi
│ │ ├── passwords
│ │ │ ├── edit_controller.rbi
│ │ │ └── update_controller.rbi
│ │ ├── post.rbi
│ │ ├── post_form.rbi
│ │ ├── post_link.rbi
│ │ ├── posts
│ │ │ ├── create_controller.rbi
│ │ │ ├── destroy_controller.rbi
│ │ │ ├── new_controller.rbi
│ │ │ └── show_controller.rbi
│ │ ├── profile.rbi
│ │ ├── profile_form.rbi
│ │ ├── profiles
│ │ │ ├── atom
│ │ │ │ └── show_controller.rbi
│ │ │ └── show_controller.rbi
│ │ ├── public
│ │ │ └── show_controller.rbi
│ │ ├── rails
│ │ │ └── application_controller.rbi
│ │ ├── remove_followed_profile_posts_from_timeline_job.rbi
│ │ ├── search
│ │ │ ├── profiles
│ │ │ │ └── index_controller.rbi
│ │ │ └── show_controller.rbi
│ │ ├── sentry
│ │ │ └── send_event_job.rbi
│ │ ├── session.rbi
│ │ ├── session_form.rbi
│ │ ├── sessions
│ │ │ ├── create_controller.rbi
│ │ │ ├── destroy_controller.rbi
│ │ │ └── new_controller.rbi
│ │ ├── settings
│ │ │ ├── emails
│ │ │ │ ├── show_controller.rbi
│ │ │ │ └── update_controller.rbi
│ │ │ ├── index_controller.rbi
│ │ │ ├── profiles
│ │ │ │ ├── show_controller.rbi
│ │ │ │ └── update_controller.rbi
│ │ │ └── users
│ │ │ │ ├── show_controller.rbi
│ │ │ │ └── update_controller.rbi
│ │ ├── sign_up
│ │ │ ├── create_controller.rbi
│ │ │ └── new_controller.rbi
│ │ ├── stamp.rbi
│ │ ├── stamp_form.rbi
│ │ ├── stamps
│ │ │ ├── create_controller.rbi
│ │ │ └── destroy_controller.rbi
│ │ ├── suggested_follow.rbi
│ │ ├── suggested_follow_form.rbi
│ │ ├── time.rbi
│ │ ├── user.rbi
│ │ ├── user_form.rbi
│ │ ├── user_profile.rbi
│ │ ├── view_component
│ │ │ ├── preview.rbi
│ │ │ ├── slotable.rbi
│ │ │ └── translatable.rbi
│ │ ├── view_components_system_test_controller.rbi
│ │ └── welcome
│ │ │ └── show_controller.rbi
│ ├── gems
│ │ ├── .gitattributes
│ │ ├── actioncable@7.1.5.1.rbi
│ │ ├── actionmailbox@7.1.5.1.rbi
│ │ ├── actionmailer@7.1.5.1.rbi
│ │ ├── actionpack@7.1.5.1.rbi
│ │ ├── actiontext@7.1.5.1.rbi
│ │ ├── actionview@7.1.5.1.rbi
│ │ ├── activejob@7.1.5.1.rbi
│ │ ├── activemodel@7.1.5.1.rbi
│ │ ├── activerecord@7.1.5.1.rbi
│ │ ├── activerecord_cursor_paginate@0.2.0.rbi
│ │ ├── activestorage@7.1.5.1.rbi
│ │ ├── activesupport@7.1.5.1.rbi
│ │ ├── addressable@2.8.7.rbi
│ │ ├── alba@3.2.0.rbi
│ │ ├── ast@2.4.2.rbi
│ │ ├── base64@0.2.0.rbi
│ │ ├── bcrypt@3.1.20.rbi
│ │ ├── benchmark@0.4.0.rbi
│ │ ├── better_html@2.1.1.rbi
│ │ ├── bigdecimal@3.1.8.rbi
│ │ ├── bindex@0.8.1.rbi
│ │ ├── bootsnap@1.18.3.rbi
│ │ ├── builder@3.3.0.rbi
│ │ ├── bullet@7.1.6.rbi
│ │ ├── capybara@3.40.0.rbi
│ │ ├── childprocess@5.0.0.rbi
│ │ ├── committee-rails@0.8.0.rbi
│ │ ├── committee@5.4.0.rbi
│ │ ├── concurrent-ruby@1.3.4.rbi
│ │ ├── connection_pool@2.4.1.rbi
│ │ ├── crass@1.0.6.rbi
│ │ ├── cssbundling-rails@1.4.0.rbi
│ │ ├── csv@3.3.0.rbi
│ │ ├── cuprite@0.15.1.rbi
│ │ ├── date@3.4.1.rbi
│ │ ├── diff-lcs@1.5.1.rbi
│ │ ├── discard@1.4.0.rbi
│ │ ├── doorkeeper@5.8.1.rbi
│ │ ├── dotenv-rails@3.1.2.rbi
│ │ ├── dotenv@3.1.2.rbi
│ │ ├── drb@2.2.1.rbi
│ │ ├── email_validator@2.2.4.rbi
│ │ ├── enumerize@2.8.1.rbi
│ │ ├── erb_lint@0.9.0.rbi
│ │ ├── erubi@1.13.0.rbi
│ │ ├── et-orbi@1.2.11.rbi
│ │ ├── factory_bot@6.4.5.rbi
│ │ ├── factory_bot_rails@6.4.3.rbi
│ │ ├── faraday-net_http@3.4.0.rbi
│ │ ├── faraday@2.12.1.rbi
│ │ ├── ferrum@0.15.rbi
│ │ ├── ffi@1.16.3.rbi
│ │ ├── fugit@1.11.1.rbi
│ │ ├── globalid@1.2.1.rbi
│ │ ├── good_job@3.29.3.rbi
│ │ ├── http_accept_language@2.1.1.rbi
│ │ ├── httparty@0.22.0.rbi
│ │ ├── i18n@1.14.6.rbi
│ │ ├── inline_svg@1.9.0.rbi
│ │ ├── io-console@0.8.0.rbi
│ │ ├── jb@0.8.2.rbi
│ │ ├── jsbundling-rails@1.3.0.rbi
│ │ ├── json@2.9.0.rbi
│ │ ├── json_schema@0.21.0.rbi
│ │ ├── language_server-protocol@3.17.0.3.rbi
│ │ ├── launchy@3.0.1.rbi
│ │ ├── letter_opener@1.10.0.rbi
│ │ ├── letter_opener_web@3.0.0.rbi
│ │ ├── lint_roller@1.1.0.rbi
│ │ ├── listen@3.9.0.rbi
│ │ ├── logger@1.6.3.rbi
│ │ ├── lograge@0.14.0.rbi
│ │ ├── loofah@2.23.1.rbi
│ │ ├── mail@2.8.1.rbi
│ │ ├── marcel@1.0.4.rbi
│ │ ├── matrix@0.4.2.rbi
│ │ ├── meta-tags@2.22.1.rbi
│ │ ├── method_source@1.1.0.rbi
│ │ ├── mini_mime@1.1.5.rbi
│ │ ├── minitest@5.25.4.rbi
│ │ ├── msgpack@1.7.2.rbi
│ │ ├── multi_xml@0.7.1.rbi
│ │ ├── mutex_m@0.3.0.rbi
│ │ ├── net-http@0.6.0.rbi
│ │ ├── net-imap@0.5.1.rbi
│ │ ├── net-pop@0.1.2.rbi
│ │ ├── net-protocol@0.2.2.rbi
│ │ ├── net-smtp@0.5.0.rbi
│ │ ├── netrc@0.11.0.rbi
│ │ ├── nio4r@2.7.4.rbi
│ │ ├── nokogiri@1.17.1.rbi
│ │ ├── oj@3.16.4.rbi
│ │ ├── openapi_parser@2.1.0.rbi
│ │ ├── parallel@1.26.3.rbi
│ │ ├── parser@3.3.6.0.rbi
│ │ ├── pg@1.5.6.rbi
│ │ ├── prism@1.2.0.rbi
│ │ ├── propshaft@0.9.0.rbi
│ │ ├── psych@5.2.2.rbi
│ │ ├── public_suffix@6.0.0.rbi
│ │ ├── puma@6.5.0.rbi
│ │ ├── pundit@2.4.0.rbi
│ │ ├── raabro@1.4.0.rbi
│ │ ├── racc@1.8.1.rbi
│ │ ├── rack-rewrite@1.5.1.rbi
│ │ ├── rack-session@2.0.0.rbi
│ │ ├── rack-test@2.1.0.rbi
│ │ ├── rack@3.0.11.rbi
│ │ ├── rackup@2.2.1.rbi
│ │ ├── rails-dom-testing@2.2.0.rbi
│ │ ├── rails-html-sanitizer@1.6.2.rbi
│ │ ├── rails-i18n@7.0.9.rbi
│ │ ├── rails@7.1.5.1.rbi
│ │ ├── rails_autolink@1.1.8.rbi
│ │ ├── rails_live_reload@0.3.6.rbi
│ │ ├── railties@7.1.5.1.rbi
│ │ ├── rainbow@3.1.1.rbi
│ │ ├── rake@13.2.1.rbi
│ │ ├── rb-fsevent@0.11.2.rbi
│ │ ├── rb-inotify@0.10.1.rbi
│ │ ├── rbi@0.2.1.rbi
│ │ ├── rdoc@6.10.0.rbi
│ │ ├── regexp_parser@2.9.3.rbi
│ │ ├── reline@0.6.0.rbi
│ │ ├── request_store@1.5.1.rbi
│ │ ├── resend@0.14.0.rbi
│ │ ├── rexml@3.3.9.rbi
│ │ ├── rspec-core@3.13.2.rbi
│ │ ├── rspec-expectations@3.13.3.rbi
│ │ ├── rspec-mocks@3.13.2.rbi
│ │ ├── rspec-rails@7.1.0.rbi
│ │ ├── rspec-support@3.13.2.rbi
│ │ ├── rubocop-ast@1.36.2.rbi
│ │ ├── rubocop-capybara@2.20.0.rbi
│ │ ├── rubocop-factory_bot@2.26.1.rbi
│ │ ├── rubocop-performance@1.22.1.rbi
│ │ ├── rubocop-rails@2.25.0.rbi
│ │ ├── rubocop-rspec@2.31.0.rbi
│ │ ├── rubocop-rspec_rails@2.28.3.rbi
│ │ ├── rubocop-sorbet@0.7.0.rbi
│ │ ├── rubocop@1.68.0.rbi
│ │ ├── ruby-progressbar@1.13.0.rbi
│ │ ├── securerandom@0.4.1.rbi
│ │ ├── sentry-rails@5.22.0.rbi
│ │ ├── sentry-ruby@5.22.0.rbi
│ │ ├── smart_properties@1.17.0.rbi
│ │ ├── spoom@1.5.0.rbi
│ │ ├── stackprof@0.2.27.rbi
│ │ ├── standard-custom@1.0.2.rbi
│ │ ├── standard-performance@1.5.0.rbi
│ │ ├── standard-rails@1.1.0.rbi
│ │ ├── standard-sorbet@0.0.2.rbi
│ │ ├── standard@1.42.1.rbi
│ │ ├── stringio@3.1.2.rbi
│ │ ├── strong_migrations@1.8.0.rbi
│ │ ├── tapioca@0.16.5.rbi
│ │ ├── thor@1.3.2.rbi
│ │ ├── timeout@0.4.2.rbi
│ │ ├── tzinfo@2.0.6.rbi
│ │ ├── unicode-display_width@2.6.0.rbi
│ │ ├── uniform_notifier@1.16.0.rbi
│ │ ├── uri@1.0.2.rbi
│ │ ├── vcr@6.2.0.rbi
│ │ ├── view_component@3.20.0.rbi
│ │ ├── web-console@4.2.1.rbi
│ │ ├── webrick@1.9.0.rbi
│ │ ├── websocket-driver@0.7.6.rbi
│ │ ├── websocket-extensions@0.1.5.rbi
│ │ ├── xpath@3.2.0.rbi
│ │ ├── yard-sorbet@0.9.0.rbi
│ │ ├── yard@0.9.37.rbi
│ │ └── zeitwerk@2.7.1.rbi
│ ├── manual
│ │ ├── account.rbi
│ │ ├── active_record
│ │ │ └── relation.rbi
│ │ ├── addressable.rbi
│ │ ├── api
│ │ │ └── v1
│ │ │ │ ├── application_controller.rbi
│ │ │ │ ├── form_errorable.rbi
│ │ │ │ └── timeline
│ │ │ │ └── show_controller.rbi
│ │ ├── application_helper.rbi
│ │ ├── commented_repost.rbi
│ │ ├── component_data_fetcher_helper.rbi
│ │ ├── controller_concerns
│ │ │ ├── api
│ │ │ │ └── authenticatable.rbi
│ │ │ ├── authenticatable.rbi
│ │ │ ├── authorizable.rbi
│ │ │ ├── email_confirmation_findable.rbi
│ │ │ └── localizable.rbi
│ │ ├── email_confirmation.rbi
│ │ ├── email_confirmation_mailer.rbi
│ │ ├── faraday.rbi
│ │ ├── flash_toast_helper.rbi
│ │ ├── form
│ │ │ └── password_validatable.rbi
│ │ ├── google
│ │ │ └── cloud
│ │ │ │ ├── pubsub.rbi
│ │ │ │ ├── pubsub
│ │ │ │ ├── credentials.rbi
│ │ │ │ ├── project.rbi
│ │ │ │ └── topic.rbi
│ │ │ │ └── tasks
│ │ │ │ └── v2
│ │ │ │ └── cloud_tasks
│ │ │ │ ├── client.rbi
│ │ │ │ └── credentials.rbi
│ │ ├── icons
│ │ │ ├── logo_icon_component.rbi
│ │ │ ├── stamped_icon_component.rbi
│ │ │ └── unstamped_icon_component.rbi
│ │ ├── internal_authenticatable.rbi
│ │ ├── kernel.rbi
│ │ ├── language_helper.rbi
│ │ ├── localizable.rbi
│ │ ├── mewst
│ │ │ └── application.rbi
│ │ ├── model_concerns
│ │ │ └── notifiable.rbi
│ │ ├── nil_class.rbi
│ │ ├── notification.rbi
│ │ ├── post.rbi
│ │ ├── post
│ │ │ ├── private_association_relation.rbi
│ │ │ └── private_relation.rbi
│ │ ├── profile.rbi
│ │ ├── profile
│ │ │ └── private_relation.rbi
│ │ ├── pubsub
│ │ │ └── subscribable.rbi
│ │ ├── repost.rbi
│ │ ├── session
│ │ │ └── private_collection_proxy.rbi
│ │ ├── text_helper.rbi
│ │ ├── time_helper.rbi
│ │ └── user.rbi
│ ├── shims
│ │ ├── loofah.rbi
│ │ └── minitest.rbi
│ └── todo.rbi
└── tapioca
│ ├── config.yml
│ └── require.rb
├── spec
├── factories
│ ├── actor.rb
│ ├── email_confirmation.rb
│ ├── link.rb
│ ├── oauth_application.rb
│ ├── oauth_oauth_access_token.rb
│ ├── post.rb
│ ├── profile.rb
│ └── user.rb
├── forms
│ └── post_form_spec.rb
├── models
│ ├── link_data_fetcher_spec.rb
│ └── url_spec.rb
├── rails_helper.rb
├── requests
│ ├── profiles
│ │ └── show_spec.rb
│ ├── sign_in
│ │ └── new_spec.rb
│ ├── sign_up
│ │ └── new_spec.rb
│ ├── v1
│ │ ├── follows
│ │ │ ├── create_spec.rb
│ │ │ └── destroy_spec.rb
│ │ ├── internal
│ │ │ ├── accounts
│ │ │ │ └── create_spec.rb
│ │ │ ├── email_confirmations
│ │ │ │ ├── challenges
│ │ │ │ │ └── create_spec.rb
│ │ │ │ ├── create_spec.rb
│ │ │ │ └── show_spec.rb
│ │ │ ├── posts
│ │ │ │ └── show_spec.rb
│ │ │ ├── profiles
│ │ │ │ └── posts
│ │ │ │ │ └── index_spec.rb
│ │ │ └── sessions
│ │ │ │ └── create_spec.rb
│ │ ├── notifications
│ │ │ └── index_spec.rb
│ │ ├── posts
│ │ │ ├── create_spec.rb
│ │ │ ├── destroy_spec.rb
│ │ │ └── show_spec.rb
│ │ ├── profiles
│ │ │ ├── me
│ │ │ │ └── update_spec.rb
│ │ │ └── posts
│ │ │ │ └── index_spec.rb
│ │ ├── stamps
│ │ │ ├── create_spec.rb
│ │ │ └── destroy_spec.rb
│ │ ├── suggested_profiles
│ │ │ ├── checks
│ │ │ │ └── create_spec.rb
│ │ │ └── index_spec.rb
│ │ ├── timeline
│ │ │ └── show_spec.rb
│ │ └── users
│ │ │ └── me
│ │ │ ├── show_spec.rb
│ │ │ └── update_spec.rb
│ └── welcome
│ │ └── show_spec.rb
├── spec_helper.rb
├── support
│ ├── capybara.rb
│ ├── committee.rb
│ ├── factory_bot.rb
│ ├── request_helpers.rb
│ └── vcr.rb
├── system
│ └── welcome
│ │ └── show_spec.rb
└── use_cases
│ ├── create_post_use_case_spec.rb
│ ├── create_suggested_follows_use_case_spec.rb
│ └── delete_post_use_case_spec.rb
├── tailwind.config.js
└── yarn.lock
/.env.development:
--------------------------------------------------------------------------------
1 | DATABASE_URL=postgresql://postgres@postgresql:5432/mewst_development
2 |
3 | MEWST_COMMUNITY_URL=https://wikino.app/s/mewst/pages/54
4 | MEWST_EMAIL_DOMAIN=mewst.com
5 | MEWST_HOST=localhost
6 | MEWST_ORIGIN_PORT=3000
7 | MEWST_PORT=3300
8 | MEWST_PRIVACY_URL=https://wikino.app/s/mewst/pages/70
9 | MEWST_SIGN_UP_STOPPER_ENABLED=false
10 | MEWST_TERMS_URL=https://wikino.app/s/mewst/pages/71
11 | MEWST_URL=http://localhost:3300
12 |
--------------------------------------------------------------------------------
/.env.test:
--------------------------------------------------------------------------------
1 | DATABASE_URL=postgresql://postgres@postgresql:5432/mewst_test
2 |
3 | MEWST_CHROME_URL: http://chrome:3333
4 | MEWST_HOST: localhost
5 |
--------------------------------------------------------------------------------
/.erb_lint.yml:
--------------------------------------------------------------------------------
1 | ---
2 | EnableDefaultLinters: true
3 | linters:
4 | SpaceInHtmlTag:
5 | # 閉じタグを次の行で書きたいので無効にする
6 | enabled: false
7 | glob: "**/*.erb"
8 | exclude:
9 | - "**/vendor/**/*"
10 | - "**/node_modules/**/*"
11 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # See https://git-scm.com/docs/gitattributes for more about git attribute files.
2 |
3 | # Mark the database schema as having been generated.
4 | db/schema.rb linguist-generated
5 |
6 | # Mark any vendored files as having been vendored.
7 | vendor/* linguist-vendored
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | /.bundle
4 | /.claude/settings.local.json
5 | /.devcontainer
6 | /.env.*.local
7 | /.env.local
8 | /.idea
9 | /.vscode
10 | /app/assets/builds/*
11 | /bin/sync
12 | /config/master.key
13 | /docker-compose.override.yml
14 | /lib/tasks/dev.rake
15 | /log/*
16 | /node_modules
17 | /private
18 | /public/uploads/*
19 | /tmp/*
20 | /vendor/bundle
21 | /yarn-error.log
22 | !/app/assets/builds/.keep
23 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "docs/claude/base"]
2 | path = docs/claude/base
3 | url = https://github.com/shimpleco/claude-docs.git
4 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | /docs
2 | /fixtures
3 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "semi": true,
4 | "singleQuote": false,
5 | "tabWidth": 2,
6 | "trailingComma": "all",
7 | "plugins": ["prettier-plugin-tailwindcss", "@ttskch/prettier-plugin-tailwindcss-anywhere"],
8 | "overrides": [
9 | {
10 | "files": "*.html.erb",
11 | "options": {
12 | "parser": "anywhere"
13 | }
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --format documentation
3 | --require rails_helper
4 |
--------------------------------------------------------------------------------
/.standard.yml:
--------------------------------------------------------------------------------
1 | extend_config:
2 | - .standard_rubocop_extensions.yml
3 |
4 | plugins:
5 | - standard-rails
6 | - standard-sorbet
7 |
--------------------------------------------------------------------------------
/CLAUDE.md:
--------------------------------------------------------------------------------
1 | # Mewst開発ガイド
2 |
3 | Mewstはマイクロブログサービスです。
4 | ユーザーは短文のポストを作成することができ、ユーザーをフォローするとタイムラインにポストが時系列で表示されます。
5 |
6 | ## 基本情報
7 |
8 | - @docs/claude/base/coding-conventions/css.md
9 | - @docs/claude/base/coding-conventions/general.md
10 | - @docs/claude/base/coding-conventions/rails.md
11 | - @docs/claude/base/coding-conventions/rspec.md
12 | - @docs/claude/base/coding-conventions/ruby.md
13 | - @docs/claude/base/command-reference.md
14 | - @docs/claude/base/repository-structure.md
15 | - @docs/claude/base/tech-stack.md
16 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: bin/puma -C config/puma.rb
2 | worker: bin/good_job start
3 |
--------------------------------------------------------------------------------
/Procfile.dev:
--------------------------------------------------------------------------------
1 | css: yarn build:css --watch
2 | js: yarn build --watch
3 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require_relative "config/application"
5 |
6 | Rails.application.load_tasks
7 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "cron": [
3 | {
4 | "command": "bin/rails suggested_follow:create",
5 | "schedule": "0 * * * *"
6 | }
7 | ],
8 | "scripts": {
9 | "dokku": {
10 | "postdeploy": "bin/rails db:migrate"
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/assets/builds/.keep:
--------------------------------------------------------------------------------
1 | NOTE:
2 | `app/assets/builds/` ディレクトリがリポジトリ上に存在しないと
3 | `assets:precompile` したとき `public/assets/` にファイルが出力されないことがある
4 | https://github.com/rails/jsbundling-rails/issues/87#issuecomment-1046365785
5 |
--------------------------------------------------------------------------------
/app/assets/images/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mewstcom/mewst/3ac44bfbed0978ba6e61d5ca44658ea91323379c/app/assets/images/avatar.png
--------------------------------------------------------------------------------
/app/assets/images/icons/caret-left-regular.svg:
--------------------------------------------------------------------------------
1 |
2 |
11 |
--------------------------------------------------------------------------------
/app/assets/images/icons/caret-right-regular.svg:
--------------------------------------------------------------------------------
1 |
2 |
11 |
--------------------------------------------------------------------------------
/app/assets/images/icons/search_fill.svg:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/application.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | /* https://fontawesome.com/docs/web/add-icons/svg-bare */
6 | .mst-fa-icon {
7 | height: 1em;
8 | vertical-align: -0.125em;
9 | width: 1em;
10 | }
11 |
12 | .mst-svg-icon {
13 | fill: currentcolor;
14 | }
15 |
--------------------------------------------------------------------------------
/app/components/application_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ApplicationComponent < ViewComponent::Base
5 | extend T::Sig
6 |
7 | delegate :mst_absolute_time, :mst_image_url, :mst_time_ago_in_words, :name_with_atname, :signed_in?, :viewer!, to: :helpers
8 | end
9 |
--------------------------------------------------------------------------------
/app/components/blank_slate_component.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 🐈⬛
5 |
6 |
7 |
8 |
9 | <%= message %>
10 |
11 |
12 | <%= content %>
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/components/blank_slate_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class BlankSlateComponent < ApplicationComponent
5 | sig { params(message: String, class_name: String).void }
6 | def initialize(message:, class_name: "")
7 | @message = message
8 | @class_name = class_name
9 | end
10 |
11 | sig { returns(String) }
12 | attr_reader :message
13 | private :message
14 |
15 | sig { returns(String) }
16 | attr_reader :class_name
17 | private :class_name
18 | end
19 |
--------------------------------------------------------------------------------
/app/components/buttons/check_suggested_profile_button_component.html.erb:
--------------------------------------------------------------------------------
1 | <%= button_to profile_check_path(target_profile.atname), {
2 | class: "btn btn-ghost no-animation rounded-full w-full",
3 | } do %>
4 | <%= t("verbs.hide") %>
5 | <% end %>
6 |
--------------------------------------------------------------------------------
/app/components/buttons/check_suggested_profile_button_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Buttons::CheckSuggestedProfileButtonComponent < ApplicationComponent
5 | sig { params(target_profile: Profile).void }
6 | def initialize(target_profile:)
7 | @target_profile = target_profile
8 | end
9 |
10 | sig { returns(Profile) }
11 | attr_reader :target_profile
12 | private :target_profile
13 | end
14 |
--------------------------------------------------------------------------------
/app/components/buttons/stamp_button_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Buttons::StampButtonComponent < ApplicationComponent
5 | sig { params(post: Post, stamp_checker: StampChecker).void }
6 | def initialize(post:, stamp_checker:)
7 | @post = post
8 | @stamp_checker = stamp_checker
9 | end
10 |
11 | sig { returns(Post) }
12 | attr_reader :post
13 | private :post
14 |
15 | sig { returns(StampChecker) }
16 | attr_reader :stamp_checker
17 | private :stamp_checker
18 | end
19 |
--------------------------------------------------------------------------------
/app/components/cards/detailed_post_card_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Cards::DetailedPostCardComponent < ApplicationComponent
5 | sig { params(post: Post, stamp_checker: StampChecker).void }
6 | def initialize(post:, stamp_checker:)
7 | @post = post
8 | @stamp_checker = stamp_checker
9 | end
10 |
11 | sig { returns(Post) }
12 | attr_reader :post
13 | private :post
14 |
15 | sig { returns(StampChecker) }
16 | attr_reader :stamp_checker
17 | private :stamp_checker
18 |
19 | sig { returns(Profile) }
20 | private def profile
21 | post.profile.not_nil!
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/app/components/cards/form_errors_card_component.html.erb:
--------------------------------------------------------------------------------
1 | " role="alert">
2 |
3 |
4 | <%= t "nouns.error" %>
5 |
6 |
7 |
8 | <% @errors.full_messages.each do |message| %>
9 | -
10 | <%= message %>
11 |
12 | <% end %>
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/components/cards/form_errors_card_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Cards::FormErrorsCardComponent < ApplicationComponent
5 | sig { params(errors: ActiveModel::Errors, class_name: String).void }
6 | def initialize(errors:, class_name: "")
7 | @errors = errors
8 | @class_name = class_name
9 | end
10 |
11 | sig { returns(String) }
12 | attr_reader :class_name
13 | private :class_name
14 |
15 | sig { returns(T::Boolean) }
16 | private def render?
17 | !@errors.empty?
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/app/components/cards/link_card_component.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <% if link.image_url.present? %>
4 | <%= image_tag(link.image_url, {
5 | class: "aspect-video max-h-[300px] object-contain w-full",
6 | loading: "lazy",
7 | size: "16x9",
8 | }) %>
9 | <% end %>
10 |
11 |
12 |
13 | <%= link.domain %>
14 |
15 |
16 |
17 | <%= link.title %>
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/components/cards/link_card_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Cards::LinkCardComponent < ApplicationComponent
5 | sig { params(link: Link).void }
6 | def initialize(link:)
7 | @link = link
8 | end
9 |
10 | sig { returns(Link) }
11 | attr_reader :link
12 | private :link
13 | end
14 |
--------------------------------------------------------------------------------
/app/components/cards/notification_card/stamp_notification_component.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%= t("messages.components.notification_card.stamped") %>
4 |
5 |
6 |
7 | <%= link_to profile_post_path(target_post.profile.atname, target_post.id) do %>
8 |
9 | <%= target_post.content %>
10 |
11 | <% end %>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/components/cards/notification_card/stamp_notification_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Cards::NotificationCard::StampNotificationComponent < ApplicationComponent
5 | sig { params(notification: Notification).void }
6 | def initialize(notification:)
7 | @notification = notification
8 | end
9 |
10 | sig { returns(Notification) }
11 | attr_reader :notification
12 | private :notification
13 |
14 | sig { returns(Post) }
15 | def target_post
16 | notification.notifiable.post.not_nil!
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/components/cards/notification_card_component.html.erb:
--------------------------------------------------------------------------------
1 | <%= render Mewst::UI::Card.new do %>
2 | <%= render Mewst::UI::Card::Body.new do %>
3 | <%= render EntryHeaders::BasicEntryHeaderComponent.new(profile: source_profile, time: notification.notified_at, follow_checker:) %>
4 |
5 | <% case notification.deserialized_notifiable_type %>
6 | <% when NotifiableType::Stamp %>
7 | <%= render Cards::NotificationCard::StampNotificationComponent.new(notification:) %>
8 | <% end %>
9 | <% end %>
10 | <% end %>
11 |
--------------------------------------------------------------------------------
/app/components/cards/post_card/body_component.html.erb:
--------------------------------------------------------------------------------
1 | ">
2 | <%= helpers.render_content(post.content) %>
3 |
4 |
--------------------------------------------------------------------------------
/app/components/cards/post_card/body_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Cards::PostCard::BodyComponent < ApplicationComponent
5 | sig { params(post: Post, class_name: String).void }
6 | def initialize(post:, class_name: "")
7 | @post = post
8 | @class_name = class_name
9 | end
10 |
11 | sig { returns(Post) }
12 | attr_reader :post
13 | private :post
14 |
15 | sig { returns(String) }
16 | attr_reader :class_name
17 | private :class_name
18 |
19 | sig { returns(Profile) }
20 | private def profile
21 | post.profile.not_nil!
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/app/components/cards/post_card/footer_component.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= render Buttons::StampButtonComponent.new(post:, stamp_checker:) %>
3 |
4 | <%= render Dropdowns::PostOptionsDropdownComponent.new(post:) %>
5 |
6 |
--------------------------------------------------------------------------------
/app/components/cards/post_card/footer_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Cards::PostCard::FooterComponent < ApplicationComponent
5 | sig { params(post: Post, stamp_checker: StampChecker).void }
6 | def initialize(post:, stamp_checker:)
7 | @post = post
8 | @stamp_checker = stamp_checker
9 | end
10 |
11 | sig { returns(Post) }
12 | attr_reader :post
13 | private :post
14 |
15 | sig { returns(StampChecker) }
16 | attr_reader :stamp_checker
17 | private :stamp_checker
18 |
19 | sig { returns(Profile) }
20 | private def profile
21 | post.profile.not_nil!
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/app/components/cards/post_nav_link_card_component.html.erb:
--------------------------------------------------------------------------------
1 | <%= render Mewst::UI::Card.new do %>
2 | <%= render Mewst::UI::Card::Body.new do %>
3 | <%= post.content.truncate(10) %>
4 | <% end %>
5 | <% end %>
6 |
--------------------------------------------------------------------------------
/app/components/cards/post_nav_link_card_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module Cards
5 | class PostNavLinkCardComponent < ApplicationComponent
6 | sig { params(post: Post).void }
7 | def initialize(post:)
8 | @post = post
9 | end
10 |
11 | sig { returns(Post) }
12 | attr_reader :post
13 | private :post
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/components/cards/profile_card_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Cards::ProfileCardComponent < ApplicationComponent
5 | renders_one :actions_menu
6 |
7 | sig { params(profile: Profile).void }
8 | def initialize(profile:)
9 | @profile = profile
10 | end
11 |
12 | sig { returns(Profile) }
13 | attr_reader :profile
14 | private :profile
15 | end
16 |
--------------------------------------------------------------------------------
/app/components/containers/basic_container_component.html.erb:
--------------------------------------------------------------------------------
1 | ">
2 | <%= content %>
3 |
4 |
--------------------------------------------------------------------------------
/app/components/containers/basic_container_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Containers::BasicContainerComponent < ApplicationComponent
5 | sig { params(class_name: String).void }
6 | def initialize(class_name: "")
7 | @class_name = class_name
8 | end
9 |
10 | sig { returns(String) }
11 | attr_reader :class_name
12 | private :class_name
13 | end
14 |
--------------------------------------------------------------------------------
/app/components/dropdowns/post_options_dropdown_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Dropdowns::PostOptionsDropdownComponent < ApplicationComponent
5 | sig { params(post: Post).void }
6 | def initialize(post:)
7 | @post = post
8 | end
9 |
10 | sig { returns(Post) }
11 | attr_reader :post
12 | private :post
13 | end
14 |
--------------------------------------------------------------------------------
/app/components/dropdowns/profile_options_dropdown_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Dropdowns::ProfileOptionsDropdownComponent < ApplicationComponent
5 | sig { params(profile: Profile).void }
6 | def initialize(profile:)
7 | @profile = profile
8 | end
9 |
10 | sig { returns(Profile) }
11 | attr_reader :profile
12 | private :profile
13 | end
14 |
--------------------------------------------------------------------------------
/app/components/footers/basic_footer_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Footers::BasicFooterComponent < ApplicationComponent
5 | end
6 |
--------------------------------------------------------------------------------
/app/components/forms/keyword_search_form_component.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_with method: :get, model: form, url: form_url do |f| %>
2 |
12 | <% end %>
13 |
--------------------------------------------------------------------------------
/app/components/forms/keyword_search_form_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Forms::KeywordSearchFormComponent < ApplicationComponent
5 | sig { params(form: KeywordSearchForm, form_url: String).void }
6 | def initialize(form:, form_url:)
7 | @form = form
8 | @form_url = form_url
9 | end
10 |
11 | sig { returns(KeywordSearchForm) }
12 | attr_reader :form
13 | private :form
14 |
15 | sig { returns(String) }
16 | attr_reader :form_url
17 | private :form_url
18 | end
19 |
--------------------------------------------------------------------------------
/app/components/forms/post_form_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Forms::PostFormComponent < ApplicationComponent
5 | sig { params(form: PostForm, from_modal: T::Boolean).void }
6 | def initialize(form:, from_modal: false)
7 | @form = form
8 | @from_modal = from_modal
9 | end
10 |
11 | sig { returns(PostForm) }
12 | attr_reader :form
13 | private :form
14 |
15 | sig { returns(T::Boolean) }
16 | attr_reader :from_modal
17 | private :from_modal
18 | end
19 |
--------------------------------------------------------------------------------
/app/components/icons/logo_icon_component.html.erb:
--------------------------------------------------------------------------------
1 | <%= render Mewst::UI::Icon.new(name: "logo", color: "base-content", size:, class_name:) %>
2 |
--------------------------------------------------------------------------------
/app/components/icons/logo_icon_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Icons::LogoIconComponent < ApplicationComponent
5 | sig { params(size: String, class_name: String).void }
6 | def initialize(size:, class_name: "")
7 | @size = size
8 | @class_name = class_name
9 | end
10 |
11 | sig { returns(String) }
12 | attr_reader :size
13 | private :size
14 |
15 | sig { returns(String) }
16 | attr_reader :class_name
17 | private :class_name
18 | end
19 |
--------------------------------------------------------------------------------
/app/components/icons/navbar_menu_icon_component.html.erb:
--------------------------------------------------------------------------------
1 | <% if active %>
2 | <%= render Mewst::UI::Icon.new(name: active_name, color: "base-content", size:) %>
3 | <% else %>
4 | <%= render Mewst::UI::Icon.new(name:, color: "gray-400", size:) %>
5 | <% end %>
6 |
--------------------------------------------------------------------------------
/app/components/images/avatar_image_component.html.erb:
--------------------------------------------------------------------------------
1 | <%= tag.div(class: "avatar") do %>
2 | <%= tag.div(class: class_names("rounded-full", class_name)) do %>
3 | <%= image_tag(image_url, alt:, loading: "lazy", size:) %>
4 | <% end %>
5 | <% end %>
6 |
--------------------------------------------------------------------------------
/app/components/images/profile_avatar_image_component.html.erb:
--------------------------------------------------------------------------------
1 | <%= render Images::AvatarImageComponent.new(image_url: profile.avatar_url, width:, alt:, class_name:) %>
2 |
--------------------------------------------------------------------------------
/app/components/layouts/basic_layout_component.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= render Navbars::TopNavbarComponent.new %>
3 |
4 |
">
5 | <%= content %>
6 |
7 |
8 | <% if with_footer %>
9 |
10 | <%= render Footers::BasicFooterComponent.new %>
11 |
12 | <% end %>
13 |
14 |
15 | <%= render Toasts::FlashToastComponent.new(flash:) %>
16 | <%= render Navbars::BottomNavbarComponent.new %>
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/components/layouts/basic_layout_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Layouts::BasicLayoutComponent < ApplicationComponent
5 | sig { params(with_footer: T::Boolean, main_class_name: String).void }
6 | def initialize(with_footer: true, main_class_name: "")
7 | @with_footer = with_footer
8 | @main_class_name = main_class_name
9 | end
10 |
11 | sig { returns(T::Boolean) }
12 | attr_reader :with_footer
13 | private :with_footer
14 |
15 | sig { returns(String) }
16 | attr_reader :main_class_name
17 | private :main_class_name
18 | end
19 |
--------------------------------------------------------------------------------
/app/components/layouts/simple_layout_component.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%= content %>
4 |
5 |
6 |
7 | <%= render Toasts::FlashToastComponent.new(flash:) %>
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/components/layouts/simple_layout_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Layouts::SimpleLayoutComponent < ApplicationComponent
5 | end
6 |
--------------------------------------------------------------------------------
/app/components/lists/post_card_list_component.html.erb:
--------------------------------------------------------------------------------
1 | " id="post-card-list">
2 | <% posts.each do |post| %>
3 | <%= render Cards::PostCardComponent.new(post:, stamp_checker:, follow_checker:) %>
4 | <% end %>
5 |
6 |
--------------------------------------------------------------------------------
/app/components/modals/base/modal_box_component.html.erb:
--------------------------------------------------------------------------------
1 | ">
2 |
7 |
8 | <%= content %>
9 |
10 |
--------------------------------------------------------------------------------
/app/components/modals/base/modal_box_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Modals::Base::ModalBoxComponent < ApplicationComponent
5 | sig { params(class_name: String).void }
6 | def initialize(class_name: "")
7 | @class_name = class_name
8 | end
9 |
10 | sig { returns(String) }
11 | attr_reader :class_name
12 | private :class_name
13 | end
14 |
--------------------------------------------------------------------------------
/app/components/modals/base/modal_component.html.erb:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/app/components/modals/base/modal_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Modals::Base::ModalComponent < ApplicationComponent
5 | sig { params(class_name: String).void }
6 | def initialize(class_name: "")
7 | @class_name = class_name
8 | end
9 |
10 | sig { returns(String) }
11 | attr_reader :class_name
12 | private :class_name
13 | end
14 |
--------------------------------------------------------------------------------
/app/components/modals/post_form_modal_component.html.erb:
--------------------------------------------------------------------------------
1 | <%= render Modals::Base::ModalComponent.new do %>
2 | <%= render Modals::Base::ModalBoxComponent.new(class_name: "bg-base-300") do %>
3 |
4 | <%= render Forms::PostFormComponent.new(form:, from_modal: true) %>
5 |
6 | <% end %>
7 | <% end %>
8 |
--------------------------------------------------------------------------------
/app/components/modals/post_form_modal_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Modals::PostFormModalComponent < ApplicationComponent
5 | sig { params(form: PostForm).void }
6 | def initialize(form:)
7 | @form = form
8 | end
9 |
10 | sig { returns(PostForm) }
11 | attr_reader :form
12 | private :form
13 | end
14 |
--------------------------------------------------------------------------------
/app/components/navbars/bottom_navbar_component.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= render NavbarMenuComponent.new(class_name: "border border-slate-400 me-auto ms-auto") %>
3 |
4 |
--------------------------------------------------------------------------------
/app/components/navbars/bottom_navbar_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Navbars::BottomNavbarComponent < ApplicationComponent
5 | end
6 |
--------------------------------------------------------------------------------
/app/components/navbars/top_navbar_component.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= render Containers::BasicContainerComponent.new do %>
3 |
4 | <%= link_to root_path do %>
5 | <%= render Icons::LogoIconComponent.new(size: "36px") %>
6 | <% end %>
7 |
8 | <%= render NavbarMenuComponent.new %>
9 |
10 | <% end %>
11 |
12 |
--------------------------------------------------------------------------------
/app/components/navbars/top_navbar_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Navbars::TopNavbarComponent < ApplicationComponent
5 | end
6 |
--------------------------------------------------------------------------------
/app/components/tabs/timeline_tabs_component.html.erb:
--------------------------------------------------------------------------------
1 | <%= render Mewst::UI::Tabs.new(class_name:) do |component| %>
2 | <% component.with_item(href: home_path, active: current_page?("/home")) do %>
3 | <%= t("nouns.home") %>
4 | <% end %>
5 |
6 | <% component.with_item(href: public_path, active: current_page?("/public")) do %>
7 | <%= t("nouns.public") %>
8 | <% end %>
9 | <% end %>
10 |
--------------------------------------------------------------------------------
/app/components/tabs/timeline_tabs_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Tabs::TimelineTabsComponent < ApplicationComponent
5 | sig { params(class_name: String).void }
6 | def initialize(class_name: "")
7 | @class_name = class_name
8 | end
9 |
10 | sig { returns(String) }
11 | attr_reader :class_name
12 | private :class_name
13 | end
14 |
--------------------------------------------------------------------------------
/app/components/toasts/flash_toast_component.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Toasts::FlashToastComponent < ApplicationComponent
5 | sig { params(flash: ActionDispatch::Flash::FlashHash).void }
6 | def initialize(flash:)
7 | @flash = flash
8 | end
9 |
10 | sig { returns(T.nilable(Symbol)) }
11 | private def flash_toast_type
12 | @flash.keys.first&.to_sym
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/controllers/accounts/new_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Accounts::NewController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 | include ControllerConcerns::EmailConfirmationFindable
8 |
9 | around_action :set_locale
10 | before_action :require_no_authentication
11 | before_action :require_succeeded_email_confirmation
12 |
13 | sig { returns(T.untyped) }
14 | def call
15 | @form = AccountForm.new(email: @email_confirmation.not_nil!.email.not_nil!)
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/README.md:
--------------------------------------------------------------------------------
1 | > [!WARNING]
2 | > `api/v1` は現在工事中です。Web APIを公開するときに修正します
3 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/application_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Api::V1::ApplicationController < ActionController::API
5 | extend T::Sig
6 | end
7 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/internal/application_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Api::V1::Internal::ApplicationController < ActionController::API
5 | extend T::Sig
6 | end
7 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/profiles/me/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Api::V1::Profiles::Me::ShowController < Api::V1::ApplicationController
5 | # include ControllerConcerns::PublicAuthenticatable
6 | #
7 | # def call
8 | # profile_resource = V1::ProfileResource.new(viewer: current_viewer!, profile: current_viewer!.profile.not_nil!)
9 | #
10 | # render(
11 | # json: {
12 | # profile: V1::ProfileSerializer.new(profile_resource).to_h
13 | # }
14 | # )
15 | # end
16 | end
17 |
--------------------------------------------------------------------------------
/app/controllers/api/v1/users/me/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Api::V1::Users::Me::ShowController < Api::V1::ApplicationController
5 | # include ControllerConcerns::PublicAuthenticatable
6 | #
7 | # def call
8 | # user_resource = V1::UserResource.new(user: current_viewer!.user.not_nil!)
9 | #
10 | # render(
11 | # json: {
12 | # user: V1::UserSerializer.new(user_resource).to_h
13 | # }
14 | # )
15 | # end
16 | end
17 |
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ApplicationController < ActionController::Base
5 | extend T::Sig
6 | end
7 |
--------------------------------------------------------------------------------
/app/controllers/communities/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Communities::ShowController < ApplicationController
5 | sig { returns(T.untyped) }
6 | def call
7 | redirect_to(Rails.configuration.mewst["community_url"], allow_other_host: true)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/controllers/controller_concerns/api/authenticatable.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::Api::Authenticatable
5 | # extend T::Sig
6 | # extend ActiveSupport::Concern
7 | #
8 | # included do
9 | # before_action :doorkeeper_authorize!
10 | # end
11 | #
12 | # sig { returns(T.nilable(Actor)) }
13 | # def current_viewer
14 | # @current_viewer ||= T.let(doorkeeper_token&.resource_owner, T.nilable(Actor))
15 | # end
16 | #
17 | # sig { returns(Actor) }
18 | # def current_viewer!
19 | # current_viewer.not_nil!
20 | # end
21 | end
22 |
--------------------------------------------------------------------------------
/app/controllers/controller_concerns/api/v1/form_errorable.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::Api::V1::FormErrorable
5 | # extend T::Sig
6 | # extend ActiveSupport::Concern
7 | #
8 | # sig { params(resource_class: T.class_of(V1::FormErrorResource), errors: ActiveModel::Errors).void }
9 | # def response_form_errors(resource_class:, errors:)
10 | # resource_errors = resource_class.from_errors(errors: errors)
11 | #
12 | # render(
13 | # json: V1::FormErrorSerializer.new(resource_errors),
14 | # status: :unprocessable_entity
15 | # )
16 | # end
17 | end
18 |
--------------------------------------------------------------------------------
/app/controllers/controller_concerns/authorizable.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::Authorizable
5 | extend T::Sig
6 | extend ActiveSupport::Concern
7 |
8 | include Pundit::Authorization
9 |
10 | sig(:final) { returns(Actor) }
11 | def pundit_user
12 | current_viewer!
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/controllers/email_confirmations/new_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class EmailConfirmations::NewController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 | include ControllerConcerns::EmailConfirmationFindable
8 |
9 | around_action :set_locale
10 | before_action :require_email_confirmation_id
11 |
12 | sig { returns(T.untyped) }
13 | def call
14 | @form = EmailConfirmationChallengeForm.new
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/controllers/links/new_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Links::NewController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 | before_action :require_authentication
10 |
11 | sig { returns(T.untyped) }
12 | def call
13 | @form = LinkDataFetcherForm.new(target_url: params[:url])
14 | @host_and_path = Url.new(params[:url]).shorten_host_and_path
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/controllers/manifests/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Manifests::ShowController < ApplicationController
5 | sig { returns(T.untyped) }
6 | def call
7 | respond_to do |format|
8 | format.json { render(layout: false) }
9 | format.any { render(plain: "Not Found", status: :not_found) }
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/controllers/password_resets/new_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class PasswordResets::NewController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 | before_action :require_no_authentication
10 |
11 | sig { returns(T.untyped) }
12 | def call
13 | @form = EmailConfirmationForm.new
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/controllers/passwords/edit_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Passwords::EditController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 | include ControllerConcerns::EmailConfirmationFindable
8 |
9 | around_action :set_locale
10 | before_action :require_no_authentication
11 | before_action :require_succeeded_email_confirmation
12 |
13 | sig { returns(T.untyped) }
14 | def call
15 | @form = PasswordResetForm.new
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/controllers/posts/new_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Posts::NewController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 | before_action :require_authentication
10 |
11 | sig { returns(T.untyped) }
12 | def call
13 | @form = PostForm.new(content: params[:content], with_frame: params[:with_frame])
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/controllers/posts/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Posts::ShowController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 |
10 | sig { returns(T.untyped) }
11 | def call
12 | @profile = Profile.kept.find_by!(atname: params[:atname])
13 | @post = @profile.posts.kept.find(params[:post_id])
14 | @stamp_checker = StampChecker.new(profile: viewer&.profile, posts: [@post])
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/controllers/privacies/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Privacies::ShowController < ApplicationController
5 | sig { returns(T.untyped) }
6 | def call
7 | redirect_to(Rails.configuration.mewst["privacy_url"], allow_other_host: true)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/controllers/profiles/atom/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Profiles::Atom::ShowController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 |
10 | sig { returns(T.untyped) }
11 | def call
12 | @profile = Profile.kept.find_by!(atname: params[:atname])
13 | @posts = @profile.posts.kept.order(published_at: :desc).limit(15)
14 |
15 | render(formats: :atom)
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/controllers/search/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Search::ShowController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 | before_action :require_authentication
10 |
11 | sig { returns(T.untyped) }
12 | def call
13 | @profiles = viewer!.checkable_suggested_followees.order(created_at: :desc).limit(30)
14 | @follow_checker = FollowChecker.new(profile: viewer!.profile.not_nil!, target_profiles: @profiles)
15 | @form = KeywordSearchForm.new
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/controllers/sessions/destroy_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Sessions::DestroyController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 | before_action :require_authentication
10 |
11 | sig { returns(T.untyped) }
12 | def call
13 | sign_out
14 |
15 | flash[:notice] = t("messages.authentication.signed_out_successfully")
16 | redirect_to root_path
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/controllers/sessions/new_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Sessions::NewController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 | before_action :require_no_authentication
10 |
11 | sig { returns(T.untyped) }
12 | def call
13 | @form = SessionForm.new
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/controllers/settings/emails/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Settings::Emails::ShowController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 | before_action :require_authentication
10 |
11 | sig { returns(T.untyped) }
12 | def call
13 | @form = EmailUpdateForm.new
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/controllers/settings/index_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Settings::IndexController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 | before_action :require_authentication
10 |
11 | sig { returns(T.untyped) }
12 | def call
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/controllers/settings/users/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Settings::Users::ShowController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 | before_action :require_authentication
10 |
11 | sig { returns(T.untyped) }
12 | def call
13 | @form = UserForm.new(
14 | locale: viewer!.locale.serialize,
15 | time_zone: viewer!.time_zone
16 | )
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/controllers/sign_up/new_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class SignUp::NewController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 | before_action :require_no_authentication
10 |
11 | sig { returns(T.untyped) }
12 | def call
13 | @form = EmailConfirmationForm.new
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/controllers/terms/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Terms::ShowController < ApplicationController
5 | sig { returns(T.untyped) }
6 | def call
7 | redirect_to(Rails.configuration.mewst["terms_url"], allow_other_host: true)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/controllers/welcome/show_controller.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class Welcome::ShowController < ApplicationController
5 | include ControllerConcerns::Authenticatable
6 | include ControllerConcerns::Localizable
7 |
8 | around_action :set_locale
9 |
10 | sig { returns(T.untyped) }
11 | def call
12 | redirect_to(home_path) if signed_in?
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/forms/application_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ApplicationForm
5 | extend T::Sig
6 |
7 | include ActiveModel::Model
8 | include ActiveModel::Attributes
9 |
10 | # @overload
11 | sig { returns(Symbol) }
12 | def self.i18n_scope
13 | :forms
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/forms/delete_post_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class DeletePostForm < ApplicationForm
5 | attribute :target_post_id, :string
6 |
7 | validates :target_post, presence: true
8 |
9 | sig { returns(T.nilable(Post)) }
10 | def target_post
11 | Post.discarded.find_by(id: target_post_id)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/forms/discard_post_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class DiscardPostForm < ApplicationForm
5 | sig { returns(T.nilable(Profile)) }
6 | attr_accessor :profile
7 |
8 | attribute :target_post_id, :string
9 |
10 | validates :profile, presence: true
11 | validates :target_post, presence: true
12 |
13 | sig { returns(T.nilable(Post)) }
14 | def target_post
15 | profile&.posts&.kept&.find_by(id: target_post_id)
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/forms/email_confirmation_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class EmailConfirmationForm < ApplicationForm
5 | attribute :email, :string
6 |
7 | validates :email, email: true, presence: true
8 | end
9 |
--------------------------------------------------------------------------------
/app/forms/email_update_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class EmailUpdateForm < ApplicationForm
5 | attribute :new_email, :string
6 |
7 | validates :new_email, email: true, presence: true
8 | validate :email_uniqueness
9 |
10 | sig { void }
11 | private def email_uniqueness
12 | if User.find_by(email: new_email)
13 | errors.add(:new_email, :uniqueness)
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/forms/form_concerns/password_validatable.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module FormConcerns::PasswordValidatable
5 | extend ActiveSupport::Concern
6 |
7 | included do
8 | validates :password, length: {minimum: User::PASSWORD_MIN_LENGTH}, presence: true
9 | validate do |record|
10 | password_value = record.password
11 |
12 | if password_value.present? && password_value.bytesize > ActiveModel::SecurePassword::MAX_PASSWORD_LENGTH_ALLOWED
13 | record.errors.add(:password, :password_too_long)
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/forms/keyword_search_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class KeywordSearchForm < ApplicationForm
5 | attribute :q, :string
6 | end
7 |
--------------------------------------------------------------------------------
/app/forms/link_data_fetcher_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class LinkDataFetcherForm < ApplicationForm
5 | attribute :target_url, :string
6 |
7 | validates :target_url, presence: true, url: true
8 |
9 | sig { void }
10 | def add_fetch_error!
11 | errors.add(:target_url, :fetch_error)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/forms/link_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class LinkForm < ApplicationForm
5 | attribute :canonical_url, :string
6 | attribute :domain, :string
7 | attribute :title, :string
8 | attribute :image_url, :string
9 |
10 | validates :canonical_url, presence: true, url: true
11 | validates :domain, presence: true
12 | validates :title, presence: true
13 | validates :image_url, url: {allow_blank: true}
14 | end
15 |
--------------------------------------------------------------------------------
/app/forms/password_reset_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class PasswordResetForm < ApplicationForm
5 | include FormConcerns::PasswordValidatable
6 |
7 | attribute :password, :string
8 | end
9 |
--------------------------------------------------------------------------------
/app/forms/post_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class PostForm < ApplicationForm
5 | attribute :content, :string
6 | attribute :canonical_url, :string, default: ""
7 | attribute :with_frame, :boolean, default: false
8 |
9 | validates :content, length: {maximum: Post::MAXIMUM_CONTENT_LENGTH}, presence: true
10 | validates :canonical_url, url: {allow_blank: true}
11 | end
12 |
--------------------------------------------------------------------------------
/app/forms/session_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class SessionForm < ApplicationForm
5 | attribute :email, :string
6 | attribute :password, :string
7 |
8 | validates :email, email: true, presence: true
9 | validates :password, presence: true
10 | validate :authentication
11 |
12 | sig { returns(T.nilable(User)) }
13 | def user
14 | @user ||= T.let(User.find_by(email:), T.nilable(User))
15 | end
16 |
17 | sig { void }
18 | private def authentication
19 | unless user&.authenticate(password)
20 | errors.add(:base, :unauthenticated)
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/app/forms/stamp_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class StampForm < ApplicationForm
5 | attribute :target_post_id, :string
6 |
7 | validates :target_post, presence: true
8 |
9 | sig { returns(T.nilable(Post)) }
10 | def target_post
11 | Post.find_by(id: target_post_id)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/forms/suggested_follow_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class SuggestedFollowForm < ApplicationForm
5 | sig { returns(T.nilable(Profile)) }
6 | attr_accessor :source_profile
7 |
8 | attribute :target_atname, :string
9 |
10 | validates :source_profile, presence: true
11 | validates :target_profile, presence: true
12 |
13 | sig { returns(T.nilable(Profile)) }
14 | def target_profile
15 | Profile.kept.find_by(atname: target_atname)
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/forms/user_form.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class UserForm < ApplicationForm
5 | attribute :locale, :string
6 | attribute :time_zone, :string
7 |
8 | validates :locale, inclusion: {in: I18n.available_locales.map(&:to_s)}, presence: true
9 | validates :time_zone, inclusion: {in: ActiveSupport::TimeZone.all.map { |tz| tz.tzinfo.name }}, presence: true
10 | end
11 |
--------------------------------------------------------------------------------
/app/helpers/flash_toast_helper.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module FlashToastHelper
5 | extend T::Sig
6 |
7 | sig { params(type: String, message: String).returns(String) }
8 | def dispatch_to_flash_toast(type:, message:)
9 | tag.div(
10 | data: {
11 | controller: "flash-toast-dispatch",
12 | flash_toast_dispatch_type_value: type,
13 | flash_toast_dispatch_message_html_value: message
14 | }
15 | )
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/helpers/language_helper.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module LanguageHelper
5 | extend T::Sig
6 |
7 | sig { params(lang: Symbol).returns(String) }
8 | def lang_option_text(lang:)
9 | text = t("nouns.#{lang}")
10 | text_native = t("nouns.#{lang}_native")
11 |
12 | if text == text_native
13 | text
14 | else
15 | "#{text} - #{text_native}"
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/helpers/profiles_helper.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module ProfilesHelper
5 | extend T::Sig
6 |
7 | sig { params(profile: Profile).returns(String) }
8 | def name_with_atname(profile:)
9 | profile.name.present? ? "#{profile.name} (@#{profile.atname})" : "@#{profile.atname}"
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/helpers/text_helper.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module TextHelper
5 | extend T::Sig
6 |
7 | sig { params(content: String).returns(String) }
8 | def render_content(content)
9 | # 2回以上の改行は1つの空行にする
10 | replaced_content = content.gsub(/\n{2,}/, "
\n")
11 | auto_link(simple_format(replaced_content), html: {class: "link link-info", target: "_blank"}, link: :urls)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/javascript/controllers/autosize-controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus";
2 | import autosize from "autosize";
3 |
4 | export default class extends Controller {
5 | initialize() {
6 | autosize(this.element);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/app/javascript/controllers/flash-toast-dispatch-controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus";
2 |
3 | import { EventDispatcher } from "../utils/event-dispatcher";
4 |
5 | export default class extends Controller {
6 | static values = {
7 | messageHtml: String,
8 | type: String,
9 | };
10 |
11 | declare readonly messageHtmlValue: string;
12 | declare readonly typeValue: string;
13 |
14 | connect() {
15 | new EventDispatcher("flash-toast:show", {
16 | type: this.typeValue,
17 | messageHtml: this.messageHtmlValue,
18 | }).dispatch();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/javascript/controllers/modal-controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus";
2 |
3 | export default class extends Controller {
4 | connect() {
5 | this.element.showModal();
6 | }
7 |
8 | close(event: CustomEvent) {
9 | // モーダルの中でリンクカードを追加したときモーダルを閉じないようにする
10 | if (event.target.dataset.action !== "turbo:submit-end->modal#close") {
11 | return;
12 | }
13 |
14 | if (event.detail.success) {
15 | this.element.close();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/javascript/utils/event-dispatcher.ts:
--------------------------------------------------------------------------------
1 | export class EventDispatcher {
2 | event!: CustomEvent;
3 |
4 | constructor(eventName: string, detail: any = {}) {
5 | this.event = new CustomEvent(eventName, {
6 | detail,
7 | });
8 | }
9 |
10 | dispatch() {
11 | document.dispatchEvent(this.event);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/jobs/add_followed_profile_posts_to_timeline_job.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class AddFollowedProfilePostsToTimelineJob < ApplicationJob
5 | sig { params(source_profile_id: T::Mewst::DatabaseId, target_profile_id: T::Mewst::DatabaseId).void }
6 | def perform(source_profile_id:, target_profile_id:)
7 | source_profile = Profile.kept.find(source_profile_id)
8 | target_profile = Profile.kept.find(target_profile_id)
9 |
10 | AddFollowedProfilePostsToTimelineUseCase.new.call(source_profile:, target_profile:)
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/jobs/add_post_to_timeline_job.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class AddPostToTimelineJob < ApplicationJob
5 | queue_with_priority PRIORITY.fetch(:high)
6 |
7 | sig { params(profile_id: T::Mewst::DatabaseId, post_id: T::Mewst::DatabaseId).void }
8 | def perform(profile_id:, post_id:)
9 | profile = Profile.kept.find(profile_id)
10 | post = Post.find(post_id)
11 |
12 | profile.home_timeline.add_post!(post:)
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/jobs/application_job.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ApplicationJob < ActiveJob::Base
5 | extend T::Sig
6 |
7 | PRIORITY = T.let({
8 | high: 0,
9 | medium: 1,
10 | low: 2
11 | }.freeze, T::Hash[Symbol, Integer])
12 |
13 | queue_as :default
14 |
15 | queue_with_priority PRIORITY.fetch(:medium)
16 |
17 | retry_on StandardError, wait: :exponentially_longer, attempts: 5
18 | end
19 |
--------------------------------------------------------------------------------
/app/jobs/create_suggested_follows_job.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class CreateSuggestedFollowsJob < ApplicationJob
5 | sig { params(source_profile_id: T::Mewst::DatabaseId).void }
6 | def perform(source_profile_id:)
7 | source_profile = Profile.kept.find(source_profile_id)
8 |
9 | CreateSuggestedFollowsUseCase.new.call(source_profile:)
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/jobs/delete_post_job.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class DeletePostJob < ApplicationJob
5 | queue_with_priority PRIORITY.fetch(:low)
6 |
7 | sig { params(target_post_id: T::Mewst::DatabaseId).void }
8 | def perform(target_post_id:)
9 | form = DeletePostForm.new(target_post_id: target_post_id)
10 |
11 | if form.valid?
12 | DeletePostUseCase.new.call(target_post: form.target_post.not_nil!)
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/jobs/fanout_post_job.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class FanoutPostJob < ApplicationJob
5 | queue_with_priority PRIORITY.fetch(:high)
6 |
7 | sig { params(post_id: T::Mewst::DatabaseId).void }
8 | def perform(post_id:)
9 | post = Post.find(post_id)
10 |
11 | FanoutPostUseCase.new.call(post:)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/jobs/remove_followed_profile_posts_from_timeline_job.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class RemoveFollowedProfilePostsFromTimelineJob < ApplicationJob
5 | sig { params(source_profile_id: T::Mewst::DatabaseId, target_profile_id: T::Mewst::DatabaseId).void }
6 | def perform(source_profile_id:, target_profile_id:)
7 | source_profile = Profile.kept.find(source_profile_id)
8 | target_profile = Profile.kept.find(target_profile_id)
9 |
10 | RemoveFollowedProfilePostsFromTimelineUseCase.new.call(source_profile:, target_profile:)
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/mailers/application_mailer.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ApplicationMailer < ActionMailer::Base
5 | extend T::Sig
6 |
7 | default from: "Mewst "
8 | end
9 |
--------------------------------------------------------------------------------
/app/mailers/email_confirmation_mailer.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | class EmailConfirmationMailer < ApplicationMailer
5 | sig { params(email_confirmation_id: T::Mewst::DatabaseId, locale: String).void }
6 | def email_confirmation(email_confirmation_id:, locale:)
7 | email_confirmation = EmailConfirmation.active.find(email_confirmation_id)
8 |
9 | @email = email_confirmation.email
10 | @code = email_confirmation.code
11 |
12 | I18n.with_locale(locale) do
13 | subject = default_i18n_subject
14 | mail(to: @email, subject:)
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/models/application_record.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ApplicationRecord < ActiveRecord::Base
5 | extend T::Sig
6 |
7 | primary_abstract_class
8 | end
9 |
--------------------------------------------------------------------------------
/app/models/email_confirmation_event.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class EmailConfirmationEvent < T::Enum
5 | enums do
6 | EmailUpdate = new("email_update")
7 | PasswordReset = new("password_reset")
8 | SignUp = new("sign_up")
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/models/follow.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Follow < ApplicationRecord
5 | belongs_to :source_profile, class_name: "Profile"
6 | belongs_to :target_profile, class_name: "Profile"
7 |
8 | sig { void }
9 | def check_suggested!
10 | SuggestedFollow.find_by(source_profile:, target_profile:)&.touch(:checked_at)
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/models/gravatar.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Gravatar
5 | extend T::Sig
6 |
7 | sig { params(email: String).void }
8 | def initialize(email:)
9 | @email = email
10 | end
11 |
12 | sig { params(size: Integer).returns(String) }
13 | def url(size:)
14 | return "" if email.blank?
15 |
16 | params = URI.encode_www_form("s" => size)
17 | "https://www.gravatar.com/avatar/#{hash}?#{params}"
18 | end
19 |
20 | sig { returns(String) }
21 | private def hash
22 | Digest::SHA256.hexdigest(email)
23 | end
24 |
25 | sig { returns(String) }
26 | attr_reader :email
27 | private :email
28 | end
29 |
--------------------------------------------------------------------------------
/app/models/home_timeline_post.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class HomeTimelinePost < ApplicationRecord
5 | belongs_to :post
6 | belongs_to :profile
7 |
8 | scope :visible, -> { where(published_at: 1.month.ago..) }
9 | scope :invisible, -> { where(published_at: ...1.month.ago) }
10 | end
11 |
--------------------------------------------------------------------------------
/app/models/link.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Link < ApplicationRecord
5 | end
6 |
--------------------------------------------------------------------------------
/app/models/locale.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Locale < T::Enum
5 | enums do
6 | En = new
7 | Ja = new
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/models/model_concerns/notifiable.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module ModelConcerns::Notifiable
5 | extend ActiveSupport::Concern
6 |
7 | included do
8 | has_one :notification, as: :notifiable, dependent: :restrict_with_exception
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/models/notifiable_type.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class NotifiableType < T::Enum
5 | enums do
6 | Stamp = new("Stamp")
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/models/notification.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Notification < ApplicationRecord
5 | extend Enumerize
6 |
7 | delegated_type :notifiable, types: (
8 | NotifiableType.values.map(&:serialize) +
9 | # HACK: 2つ以上のモデル名を指定しないと型エラーになるため、notifiable では必要ないがNilClassを追加している
10 | # https://wikino.app/s/shimbaco/pages/345
11 | ["NilClass"]
12 | )
13 |
14 | belongs_to :source_profile, class_name: "Profile"
15 | belongs_to :target_profile, class_name: "Profile"
16 |
17 | sig { returns(NotifiableType) }
18 | def deserialized_notifiable_type
19 | NotifiableType.deserialize(notifiable_type)
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/app/models/oauth_access_token.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class OauthAccessToken < Doorkeeper::AccessToken
5 | extend T::Sig
6 |
7 | belongs_to :resource_owner, class_name: "Actor"
8 | end
9 |
--------------------------------------------------------------------------------
/app/models/oauth_application.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class OauthApplication < Doorkeeper::Application
5 | extend T::Sig
6 |
7 | MEWST_WEB_UID = "mewst-web"
8 |
9 | sig { returns(OauthApplication) }
10 | def self.mewst_web
11 | find_by!(uid: MEWST_WEB_UID)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/models/post_link.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class PostLink < ApplicationRecord
5 | belongs_to :post
6 | belongs_to :link
7 | end
8 |
--------------------------------------------------------------------------------
/app/models/profile/postability.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Profile::Postability
5 | extend T::Sig
6 |
7 | sig { params(profile: Profile).void }
8 | def initialize(profile:)
9 | @profile = profile
10 | end
11 |
12 | sig { params(post: Post).void }
13 | def delete_post(post:)
14 | ActiveRecord::Base.transaction do
15 | post.destroy!
16 | end
17 | end
18 |
19 | sig { returns(Profile) }
20 | attr_reader :profile
21 | private :profile
22 | end
23 |
--------------------------------------------------------------------------------
/app/models/profile_avatar_kind.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ProfileAvatarKind < T::Enum
5 | enums do
6 | Default = new("default")
7 | External = new("external")
8 | Gravatar = new("gravatar")
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/models/profile_owner_type.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ProfileOwnerType < T::Enum
5 | enums do
6 | User = new("User")
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/models/session.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Session < ApplicationRecord
5 | COOKIE_KEY = :mewst_session_token
6 |
7 | has_secure_token
8 |
9 | belongs_to :actor
10 |
11 | sig { params(ip_address: T.nilable(String), user_agent: T.nilable(String), signed_in_at: ActiveSupport::TimeWithZone).returns(Session) }
12 | def self.start!(ip_address:, user_agent:, signed_in_at: Time.zone.now)
13 | create!(
14 | ip_address: ip_address || "",
15 | user_agent: user_agent || "",
16 | signed_in_at:
17 | )
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/app/models/sign_up_stopper.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class SignUpStopper
5 | extend T::Sig
6 |
7 | sig { returns(T::Boolean) }
8 | def self.enabled?
9 | Rails.configuration.mewst["sign_up_stopper_enabled"] == true
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/models/stamp.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Stamp < ApplicationRecord
5 | include ModelConcerns::Notifiable
6 |
7 | belongs_to :post
8 | belongs_to :profile
9 |
10 | sig { void }
11 | def notify!
12 | Notification.where(
13 | source_profile: profile,
14 | target_profile: post.not_nil!.profile,
15 | notifiable: self
16 | ).first_or_create!(notified_at: Time.current)
17 |
18 | nil
19 | end
20 |
21 | sig { void }
22 | def unnotify!
23 | notification&.destroy!
24 |
25 | nil
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/app/models/suggested_follow.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class SuggestedFollow < ApplicationRecord
5 | belongs_to :source_profile, class_name: "Profile"
6 | belongs_to :target_profile, class_name: "Profile"
7 |
8 | scope :not_checked, -> { where(checked_at: nil) }
9 | end
10 |
--------------------------------------------------------------------------------
/app/models/user.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class User < ApplicationRecord
5 | extend Enumerize
6 |
7 | PASSWORD_MIN_LENGTH = 8
8 |
9 | enumerize :locale, in: I18n.available_locales
10 |
11 | has_many :actors, dependent: :restrict_with_exception
12 | has_one :user_profile, dependent: :restrict_with_exception
13 | has_one :profile, through: :user_profile
14 |
15 | has_secure_password
16 |
17 | validates :email, presence: true, uniqueness: true
18 |
19 | sig { returns(Actor) }
20 | def first_actor
21 | actors.find_by!(profile:)
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/app/models/user_profile.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class UserProfile < ApplicationRecord
5 | belongs_to :user
6 | belongs_to :profile
7 | end
8 |
--------------------------------------------------------------------------------
/app/models/v1/response_error_code.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::ResponseErrorCode < T::Enum
5 | enums do
6 | InvalidInputData = new("invalid_input_data")
7 | NotFound = new("not_found")
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/policies/post_policy.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class PostPolicy < ApplicationPolicy
5 | sig { returns(T::Boolean) }
6 | def destroy?
7 | profile == T.cast(record, Post).profile
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/policies/profile_policy.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ProfilePolicy < ApplicationPolicy
5 | sig { returns(T::Boolean) }
6 | def show?
7 | profile == T.cast(record, Post).profile
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/resources/concerns/resource_concerns/error_responsable.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module ResourceConcerns::ErrorResponsable
5 | extend T::Sig
6 | extend T::Helpers
7 |
8 | interface!
9 |
10 | sig { abstract.returns(V1::ResponseErrorCode) }
11 | def code
12 | end
13 |
14 | sig { abstract.returns(String) }
15 | def message
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/resources/v1/application_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::ApplicationResource
5 | extend T::Sig
6 | end
7 |
--------------------------------------------------------------------------------
/app/resources/v1/email_confirmation_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::EmailConfirmationResource < V1::ApplicationResource
5 | delegate :id, :email, :event, to: :email_confirmation
6 |
7 | sig { params(email_confirmation: EmailConfirmation).void }
8 | def initialize(email_confirmation:)
9 | @email_confirmation = email_confirmation
10 | end
11 |
12 | sig { returns(T.nilable(String)) }
13 | def succeeded_at
14 | email_confirmation.succeeded_at&.iso8601
15 | end
16 |
17 | sig { returns(EmailConfirmation) }
18 | attr_reader :email_confirmation
19 | private :email_confirmation
20 | end
21 |
--------------------------------------------------------------------------------
/app/resources/v1/follow_form_error_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::FollowFormErrorResource < V1::FormErrorResource
5 | sig { override.returns(T.nilable(String)) }
6 | def field
7 | case error.attribute
8 | when :target_atname
9 | "atname"
10 | else
11 | error.attribute.to_s
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/resources/v1/post_form_error_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::PostFormErrorResource < V1::FormErrorResource
5 | sig { override.returns(T.nilable(String)) }
6 | def field
7 | case error.attribute
8 | when :target_post
9 | "post_id"
10 | else
11 | error.attribute.to_s
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/resources/v1/response_error_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::ResponseErrorResource < V1::ApplicationResource
5 | include ResourceConcerns::ErrorResponsable
6 |
7 | sig { override.returns(String) }
8 | attr_reader :message
9 |
10 | sig { override.returns(V1::ResponseErrorCode) }
11 | attr_reader :code
12 |
13 | sig { params(code: V1::ResponseErrorCode, message: String).void }
14 | def initialize(code:, message:)
15 | @code = code
16 | @message = message
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/resources/v1/session_form_error_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::SessionFormErrorResource < V1::FormErrorResource
5 | sig { override.returns(T.nilable(String)) }
6 | def field
7 | case error.attribute
8 | when :base
9 | "email_or_password"
10 | else
11 | error.attribute.to_s
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/resources/v1/stamp_form_error_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::StampFormErrorResource < V1::FormErrorResource
5 | sig { override.returns(T.nilable(String)) }
6 | def field
7 | case error.attribute
8 | when :target_post
9 | "post_id"
10 | else
11 | error.attribute.to_s
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/resources/v1/suggested_follow_form_error_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::SuggestedFollowFormErrorResource < V1::FormErrorResource
5 | sig { override.returns(T.nilable(String)) }
6 | def field
7 | case error.attribute
8 | when :target_profile
9 | "atname"
10 | else
11 | error.attribute.to_s
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/resources/v1/unfollow_form_error_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::UnfollowFormErrorResource < V1::FormErrorResource
5 | sig { override.returns(T.nilable(String)) }
6 | def field
7 | case error.attribute
8 | when :target_profile
9 | "atname"
10 | else
11 | error.attribute.to_s
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/resources/v1/user_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::UserResource < V1::ApplicationResource
5 | delegate :id, :locale, :time_zone, to: :user
6 |
7 | sig { params(user: User).void }
8 | def initialize(user:)
9 | @user = user
10 | end
11 |
12 | sig { returns(User) }
13 | attr_reader :user
14 | private :user
15 | end
16 |
--------------------------------------------------------------------------------
/app/resources/v1/via_resource.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::ViaResource < V1::ApplicationResource
5 | delegate :name, to: :oauth_application
6 |
7 | sig { params(oauth_application: OauthApplication).void }
8 | def initialize(oauth_application:)
9 | @oauth_application = oauth_application
10 | end
11 |
12 | sig { returns(OauthApplication) }
13 | attr_reader :oauth_application
14 | private :oauth_application
15 | end
16 |
--------------------------------------------------------------------------------
/app/serializers/v1/account_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::AccountSerializer < V1::ApplicationSerializer
5 | root_key :account
6 |
7 | one :oauth_access_token, resource: V1::OauthAccessTokenSerializer
8 | one :profile, resource: V1::ProfileSerializer, &:profile_resource
9 | one :user, resource: V1::UserSerializer
10 | end
11 |
--------------------------------------------------------------------------------
/app/serializers/v1/application_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | class V1::ApplicationSerializer
5 | extend T::Sig
6 |
7 | include Alba::Resource
8 | end
9 |
--------------------------------------------------------------------------------
/app/serializers/v1/email_confirmation_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::EmailConfirmationSerializer < V1::ApplicationSerializer
5 | root_key :email_confirmation, :email_confirmations
6 |
7 | attributes :id, :email, :event, :succeeded_at
8 | end
9 |
--------------------------------------------------------------------------------
/app/serializers/v1/form_error_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::FormErrorSerializer < V1::ApplicationSerializer
5 | root_key :error, :errors
6 |
7 | attributes :code, :field, :message
8 | end
9 |
--------------------------------------------------------------------------------
/app/serializers/v1/notification_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | class V1::NotificationSerializer < V1::ApplicationSerializer
5 | root_key :notification, :notifications
6 |
7 | attributes :id, :kind, :notified_at
8 |
9 | one :source_profile, resource: V1::ProfileSerializer
10 |
11 | one :item, resource: ->(resource) {
12 | case resource
13 | when V1::StampNotificationItemResource
14 | V1::StampNotificationItemSerializer
15 | else
16 | raise "Unknown resource class: #{resource.class.inspect}"
17 | end
18 | }
19 | end
20 |
--------------------------------------------------------------------------------
/app/serializers/v1/oauth_access_token_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::OauthAccessTokenSerializer < V1::ApplicationSerializer
5 | root_key :oauth_access_token, :oauth_access_tokens
6 |
7 | attributes :token
8 | end
9 |
--------------------------------------------------------------------------------
/app/serializers/v1/page_info_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | class V1::PageInfoSerializer < V1::ApplicationSerializer
5 | root_key :page_info
6 |
7 | attributes :end_cursor
8 | attributes :has_next_page
9 | attributes :has_previous_page
10 | attributes :start_cursor
11 | end
12 |
--------------------------------------------------------------------------------
/app/serializers/v1/post_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | class V1::PostSerializer < V1::ApplicationSerializer
5 | root_key :post, :posts
6 |
7 | attributes :id, :content, :published_at, :viewer_has_stamped
8 |
9 | one :profile, resource: V1::ProfileSerializer
10 | one :via, resource: V1::ViaSerializer
11 | end
12 |
--------------------------------------------------------------------------------
/app/serializers/v1/profile_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | class V1::ProfileSerializer < V1::ApplicationSerializer
5 | root_key :profile, :profiles
6 |
7 | attributes :id, :atname, :name, :description, :avatar_url, :viewer_has_followed
8 | end
9 |
--------------------------------------------------------------------------------
/app/serializers/v1/response_error_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::ResponseErrorSerializer < V1::ApplicationSerializer
5 | root_key :error, :errors
6 |
7 | attributes :code, :message
8 | end
9 |
--------------------------------------------------------------------------------
/app/serializers/v1/stamp_notification_item_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | class V1::StampNotificationItemSerializer < V1::ApplicationSerializer
5 | one :source_profile, resource: V1::ProfileSerializer
6 | one :target_post, resource: V1::PostSerializer
7 | end
8 |
--------------------------------------------------------------------------------
/app/serializers/v1/user_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class V1::UserSerializer < V1::ApplicationSerializer
5 | root_key :user, :users
6 |
7 | attributes :id, :locale, :time_zone
8 | end
9 |
--------------------------------------------------------------------------------
/app/serializers/v1/via_serializer.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | class V1::ViaSerializer < V1::ApplicationSerializer
5 | attributes :name
6 | end
7 |
--------------------------------------------------------------------------------
/app/use_cases/add_followed_profile_posts_to_timeline_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class AddFollowedProfilePostsToTimelineUseCase < ApplicationUseCase
5 | sig { params(source_profile: Profile, target_profile: Profile).void }
6 | def call(source_profile:, target_profile:)
7 | target_posts = target_profile.posts.kept.order(published_at: :desc).limit(30)
8 |
9 | ActiveRecord::Base.transaction do
10 | target_posts.each do |post|
11 | source_profile.home_timeline.add_post!(post:)
12 | end
13 | end
14 |
15 | nil
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/use_cases/application_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ApplicationUseCase
5 | extend T::Sig
6 | end
7 |
--------------------------------------------------------------------------------
/app/use_cases/check_suggested_follow_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class CheckSuggestedFollowUseCase < ApplicationUseCase
5 | sig { params(source_profile: Profile, target_profile: Profile).void }
6 | def call(source_profile:, target_profile:)
7 | suggested_follow = source_profile.suggested_follows.find_by(target_profile:)
8 | return unless suggested_follow
9 |
10 | suggested_follow.touch(:checked_at)
11 |
12 | nil
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/use_cases/confirm_email_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class ConfirmEmailUseCase < ApplicationUseCase
5 | class Result < T::Struct
6 | const :email_confirmation, EmailConfirmation
7 | end
8 |
9 | sig { params(viewer: T.nilable(Actor), email_confirmation: EmailConfirmation).returns(Result) }
10 | def call(viewer:, email_confirmation:)
11 | ActiveRecord::Base.transaction do
12 | email_confirmation.success!
13 | email_confirmation.process_after_success!(viewer:)
14 | end
15 |
16 | Result.new(email_confirmation:)
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/use_cases/create_link_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class CreateLinkUseCase < ApplicationUseCase
5 | class Result < T::Struct
6 | const :link, Link
7 | end
8 |
9 | sig { params(canonical_url: String, domain: String, title: String, image_url: String).returns(Result) }
10 | def call(canonical_url:, domain:, title:, image_url:)
11 | link = Link.new(canonical_url:, domain:, title:, image_url:)
12 |
13 | link.save!
14 |
15 | Result.new(link:)
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/use_cases/create_session_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class CreateSessionUseCase < ApplicationUseCase
5 | class Result < T::Struct
6 | const :session, Session
7 | end
8 |
9 | sig { params(actor: Actor, ip_address: T.nilable(String), user_agent: T.nilable(String)).returns(Result) }
10 | def call(actor:, ip_address:, user_agent:)
11 | session = ActiveRecord::Base.transaction do
12 | actor.sessions.start!(ip_address:, user_agent:)
13 | end
14 |
15 | Result.new(session:)
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/app/use_cases/create_suggested_follows_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class CreateSuggestedFollowsUseCase < ApplicationUseCase
5 | sig { params(source_profile: Profile).void }
6 | def call(source_profile:)
7 | source_profile.create_suggested_follows!
8 |
9 | nil
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/use_cases/delete_post_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class DeletePostUseCase < ApplicationUseCase
5 | sig { params(target_post: Post).void }
6 | def call(target_post:)
7 | ActiveRecord::Base.transaction do
8 | target_post.stamps.find_each do |stamp|
9 | stamp.notification&.destroy!
10 | stamp.reload.destroy!
11 | end
12 |
13 | target_post.home_timeline_posts.find_each(&:destroy!)
14 | target_post.post_link&.destroy!
15 | target_post.reload.destroy!
16 | end
17 |
18 | nil
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/app/use_cases/delete_stamp_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class DeleteStampUseCase < ApplicationUseCase
5 | class Result < T::Struct
6 | const :post, Post
7 | end
8 |
9 | sig { params(viewer: Actor, target_post: Post).returns(Result) }
10 | def call(viewer:, target_post:)
11 | stamp = viewer.stamps.find_by(post: target_post)
12 |
13 | ApplicationRecord.transaction do
14 | stamp&.unnotify!
15 | stamp&.reload&.destroy!
16 | end
17 |
18 | Result.new(post: target_post.reload)
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/app/use_cases/discard_post_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class DiscardPostUseCase < ApplicationUseCase
5 | sig { params(target_post: Post).void }
6 | def call(target_post:)
7 | ApplicationRecord.transaction do
8 | target_post.discard!
9 | DeletePostJob.perform_later(target_post_id: target_post.id.not_nil!)
10 | end
11 |
12 | nil
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/use_cases/fanout_post_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class FanoutPostUseCase < ApplicationUseCase
5 | class Result < T::Struct
6 | const :post, Post
7 | end
8 |
9 | sig { params(post: Post).returns(Result) }
10 | def call(post:)
11 | followers = post.profile.not_nil!.followers
12 |
13 | batch = GoodJob::Batch.new
14 | batch.add do
15 | followers.find_each do |follower|
16 | AddPostToTimelineJob.perform_later(profile_id: follower.id.not_nil!, post_id: post.id.not_nil!)
17 | end
18 | end
19 | batch.enqueue
20 |
21 | Result.new(post:)
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/app/use_cases/remove_followed_profile_posts_from_timeline_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class RemoveFollowedProfilePostsFromTimelineUseCase < ApplicationUseCase
5 | sig { params(source_profile: Profile, target_profile: Profile).void }
6 | def call(source_profile:, target_profile:)
7 | source_profile.home_timeline_posts.joins(:post).merge(target_profile.posts).find_each do |home_timeline_post|
8 | home_timeline_post.destroy!
9 | end
10 |
11 | nil
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/app/use_cases/update_password_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class UpdatePasswordUseCase < ApplicationUseCase
5 | sig { params(email: String, password: String).void }
6 | def call(email:, password:)
7 | User.find_by!(email:).update!(password:)
8 |
9 | nil
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/use_cases/update_user_use_case.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class UpdateUserUseCase < ApplicationUseCase
5 | class Result < T::Struct
6 | const :user, User
7 | end
8 |
9 | sig { params(viewer: Actor, locale: String, time_zone: String).returns(Result) }
10 | def call(viewer:, locale:, time_zone:)
11 | viewer.user.not_nil!.update!(locale:, time_zone:)
12 |
13 | Result.new(user: viewer.user.not_nil!)
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/validators/url_validator.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class UrlValidator < ActiveModel::EachValidator
5 | extend T::Sig
6 |
7 | sig { params(record: ApplicationForm, attribute: Symbol, value: String).void }
8 | def validate_each(record, attribute, value)
9 | return if value.blank?
10 |
11 | unless Url.new(value).valid?
12 | record.errors.add(attribute, :url)
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/views/checks/create/call.html.erb:
--------------------------------------------------------------------------------
1 | <% if @form.errors.any? %>
2 |
3 |
4 | <%= dispatch_to_flash_toast(type: "alert", message: @form.errors.full_messages.first) %>
5 |
6 |
7 | <% else %>
8 |
9 | <% end %>
10 |
--------------------------------------------------------------------------------
/app/views/email_confirmation_mailer/email_confirmation.en.html.erb:
--------------------------------------------------------------------------------
1 | Hello, <%= @email %>.
2 |
3 | The confirmation code is as follows.
4 |
5 | <%= @code %>
6 |
7 | The confirmation code is valid for 15 minutes.
8 |
9 | If this email does not concern you, please ignore it.
10 |
11 | Mewst
12 | <%= link_to ENV.fetch("MEWST_URL"), ENV.fetch("MEWST_URL") %>
13 |
--------------------------------------------------------------------------------
/app/views/email_confirmation_mailer/email_confirmation.ja.html.erb:
--------------------------------------------------------------------------------
1 | <%= @email %> さん、こんにちは。
2 |
3 | 確認用コードは下記になります。
4 |
5 | <%= @code %>
6 |
7 | 確認用コードの有効期間は15分です。
8 |
9 | もしこのメールに心当たりが無い場合は無視してください。
10 |
11 | Mewst
12 | <%= link_to ENV.fetch("MEWST_URL"), ENV.fetch("MEWST_URL") %>
13 |
--------------------------------------------------------------------------------
/app/views/layouts/mailer.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 | <%= yield %>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/views/layouts/mailer.text.erb:
--------------------------------------------------------------------------------
1 | <%= yield %>
2 |
--------------------------------------------------------------------------------
/app/views/links/create/call.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= render Cards::LinkCardComponent.new(link: @link) %>
5 |
6 |
12 |
13 |
14 | <%= hidden_field_tag "post_form[canonical_url]", @link.canonical_url %>
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/views/links/new/call.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= form_with model: @form, url: link_list_path do |f| %>
3 | <%= render Cards::FormErrorsCardComponent.new(errors: f.object.errors) %>
4 |
5 | <%= f.hidden_field :target_url %>
6 |
7 | <%= f.button(
8 | class: "btn btn-ghost btn-xs no-animation rounded-full textarea-bordered",
9 | type: :submit
10 | ) do %>
11 | <%= t("verbs.add_link_card", host_and_path: @host_and_path) %>
12 | <% end %>
13 | <% end %>
14 |
15 |
--------------------------------------------------------------------------------
/app/views/posts/create/call.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%= render Forms::PostFormComponent.new(form: @form) %>
4 |
5 |
6 |
7 |
8 |
9 | <%= render Cards::PostCardComponent.new(post: @post, stamp_checker: @stamp_checker) %>
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/views/posts/new/call.html.erb:
--------------------------------------------------------------------------------
1 | <% title = t("meta.title.posts.new") %>
2 | <% set_meta_tags(title:) %>
3 |
4 | <%= render ::Layouts::BasicLayoutComponent.new(with_footer: false, main_class_name: "grid place-items-center") do %>
5 | <%= render Containers::BasicContainerComponent.new do %>
6 | <% if @form.with_frame %>
7 |
8 | <%= render Modals::PostFormModalComponent.new(form: @form) %>
9 |
10 | <% else %>
11 | <%= render Forms::PostFormComponent.new(form: @form) %>
12 | <% end %>
13 | <% end %>
14 | <% end %>
15 |
--------------------------------------------------------------------------------
/app/views/stamps/create/call.html.erb:
--------------------------------------------------------------------------------
1 | <% if @form.errors.any? %>
2 |
3 |
4 | <%= dispatch_to_flash_toast(type: "alert", message: @form.errors.full_messages.first) %>
5 |
6 |
7 | <% else %>
8 |
9 |
10 | <%= render Buttons::StampButtonComponent.new(post: @post, stamp_checker: @stamp_checker) %>
11 |
12 |
13 | <% end %>
14 |
--------------------------------------------------------------------------------
/bin/check:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | def system!(*args)
4 | system(*args, exception: true)
5 | end
6 |
7 | [
8 | "bin/rails zeitwerk:check",
9 | "bin/rails sorbet:update",
10 | "yarn prettier . --write",
11 | "bin/erb_lint --lint-all",
12 | "bin/standardrb",
13 | "bin/srb tc",
14 | "bin/rspec"
15 | ].each do |command|
16 | puts "=== `#{command}` を実行中..."
17 | system!(command)
18 | end
19 |
--------------------------------------------------------------------------------
/bin/dev:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if ! foreman version &> /dev/null
4 | then
5 | echo "Installing foreman..."
6 | gem install foreman
7 | fi
8 |
9 | foreman start -f Procfile.dev "$@"
10 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | APP_PATH = File.expand_path("../config/application", __dir__)
3 | require_relative "../config/boot"
4 | require "rails/commands"
5 |
--------------------------------------------------------------------------------
/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require_relative "../config/boot"
3 | require "rake"
4 | Rake.application.run
5 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # typed: false
2 |
3 | # This file is used by Rack-based servers to start the application.
4 |
5 | require_relative "config/environment"
6 |
7 | run Rails.application
8 | Rails.application.load_server
9 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
5 |
6 | require "bundler/setup" # Set up gems listed in the Gemfile.
7 | require "bootsnap/setup" # Speed up boot time by caching expensive operations.
8 |
--------------------------------------------------------------------------------
/config/credentials.yml.enc:
--------------------------------------------------------------------------------
1 | Et2zgyIQbrHxgJdzZwfsXvyob+t+Nc7iJ41haR2UcAV0oZvGR0QyXLry8w6wM08f/JA7u0QnUsIO2zW6+VpScvLC/PQJet3fdRX0LdqodDOVXriFc+23W5kmvibl4j0u6YTlQG5pbe7/R27KmY9Q8X1nTtrS8QGLgC8G/aDWLyitDad14/p0elVZycbqfAXuIGyXIWiYbjjrZv3nPwTiu4YcGAzrh+q1FTSdvF9q0vbNVem/9dWhot8tzt8WWcVgJMEjtQcL2RJ8/53eg1brWJuZSbtID27HG4T/JpPkhfT4CsvUHzK2/9mTjTU48ClkJzveHX/pKWrxa8aI7e15Vf1gN4muwxn0Lb7gfXRQNj0u5ZKMsfm+BAhVJgPA8yEGk82vXHE+OSFyPW2MvWDvJt+ryTqSx0HfmzXo--zVVC6t6rowoy67J8--NsgEHE4XFy73eRCDUDWWjQ==
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | default: &default
2 | adapter: postgresql
3 | encoding: unicode
4 | # For details on connection pooling, see rails configuration guide
5 | # http://guides.rubyonrails.org/configuring.html#database-pooling
6 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
7 | url: <%= ENV.fetch("DATABASE_URL") %>
8 |
9 | development:
10 | <<: *default
11 |
12 | test:
13 | <<: *default
14 |
15 | production:
16 | <<: *default
17 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | # Load the Rails application.
5 | require_relative "application"
6 |
7 | # Initialize the Rails application.
8 | Rails.application.initialize!
9 |
--------------------------------------------------------------------------------
/config/initializers/alba.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | Alba.backend = :oj_rails
5 |
--------------------------------------------------------------------------------
/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 |
3 | # Be sure to restart your server when you modify this file.
4 |
5 | # Version of your assets, change this if you want to expire all your assets.
6 | Rails.application.config.assets.version = "1.0"
7 |
8 | # Add additional assets to the asset load path.
9 | # Rails.application.config.assets.paths << Emoji.images_path
10 |
11 | # Precompile additional assets.
12 | # application.js, application.css, and all non-JS/CSS in the app/assets
13 | # folder are already added.
14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css )
15 |
--------------------------------------------------------------------------------
/config/initializers/enable_yjit.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | # Automatically enable YJIT as of Ruby 3.3, as it brings very
5 | # sizeable performance improvements.
6 |
7 | # If you are deploying to a memory constrained environment
8 | # you may want to delete this file, but otherwise it's free
9 | # performance.
10 | if defined? RubyVM::YJIT.enable
11 | Rails.application.config.after_initialize do
12 | RubyVM::YJIT.enable
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | # Be sure to restart your server when you modify this file.
5 |
6 | # Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file.
7 | # Use this to limit dissemination of sensitive information.
8 | # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
9 | Rails.application.config.filter_parameters += [
10 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
11 | ]
12 |
--------------------------------------------------------------------------------
/config/initializers/good_job.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | Rails.application.configure do
5 | config.good_job.max_threads = 3
6 | config.good_job.queues = "*"
7 | # https://github.com/bensheldon/good_job/tree/00f80cb127df622234c2a899e963367cc1b387df#job-priority
8 | config.good_job.smaller_number_is_higher_priority = true
9 | end
10 |
--------------------------------------------------------------------------------
/config/initializers/inline_svg.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | InlineSvg.configure do |config|
5 | config.asset_finder = InlineSvg::PropshaftAssetFinder
6 | end
7 |
--------------------------------------------------------------------------------
/config/initializers/not_nil.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module Kernel
5 | def not_nil!
6 | self
7 | end
8 | end
9 |
10 | class NilClass
11 | def not_nil!
12 | raise TypeError.new("Expected not to be nil")
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/config/initializers/permissions_policy.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | # Be sure to restart your server when you modify this file.
5 |
6 | # Define an application-wide HTTP permissions policy. For further
7 | # information see: https://developers.google.com/web/updates/2018/06/feature-policy
8 |
9 | # Rails.application.config.permissions_policy do |policy|
10 | # policy.camera :none
11 | # policy.gyroscope :none
12 | # policy.microphone :none
13 | # policy.usb :none
14 | # policy.fullscreen :self
15 | # policy.payment :self, "https://secure.example.com"
16 | # end
17 |
--------------------------------------------------------------------------------
/config/initializers/resend.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | if Rails.env.production?
5 | Resend.api_key = Rails.configuration.mewst["resend_api_key"]
6 | end
7 |
--------------------------------------------------------------------------------
/config/initializers/sentry.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | Sentry.init do |config|
5 | config.dsn = Rails.configuration.mewst["sentry_dsn"]
6 | config.breadcrumbs_logger = %i[active_support_logger http_logger]
7 |
8 | # Set traces_sample_rate to 1.0 to capture 100%
9 | # of transactions for performance monitoring.
10 | # We recommend adjusting this value in production.
11 | config.traces_sample_rate = 0.5
12 |
13 | # Set profiles_sample_rate to profile 100%
14 | # of sampled transactions.
15 | # We recommend adjusting this value in production.
16 | config.profiles_sample_rate = 0.5
17 | end
18 |
--------------------------------------------------------------------------------
/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | Rails.application.config.session_store :cookie_store,
5 | key: "_mewst_session",
6 | expire_after: 10.years
7 |
--------------------------------------------------------------------------------
/config/initializers/sorbet.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | T::Configuration.enable_final_checks_on_hooks
5 |
--------------------------------------------------------------------------------
/config/initializers/time_formats.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | Date::DATE_FORMATS[:ym] = "%Y-%m"
5 | Time::DATE_FORMATS[:ymd] = "%Y-%m-%d"
6 | Time::DATE_FORMATS[:ymdhm] = "%Y-%m-%d %H:%M"
7 |
--------------------------------------------------------------------------------
/config/initializers/types.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | module T::Mewst
5 | extend T::Sig
6 |
7 | DatabaseId = T.type_alias { String }
8 | end
9 |
--------------------------------------------------------------------------------
/config/locales/actionmailer.en.yml:
--------------------------------------------------------------------------------
1 | en:
2 | email_confirmation_mailer:
3 | email_confirmation:
4 | subject: "[Mewst] Confirmation code"
5 |
--------------------------------------------------------------------------------
/config/locales/actionmailer.ja.yml:
--------------------------------------------------------------------------------
1 | ja:
2 | email_confirmation_mailer:
3 | email_confirmation:
4 | subject: "[Mewst] 確認用コード"
5 |
--------------------------------------------------------------------------------
/config/locales/activerecord.en.yml:
--------------------------------------------------------------------------------
1 | en:
2 | activerecord:
3 | attributes:
4 | profile:
5 | atname: At name
6 | avatar_kinds:
7 | default: Default
8 | gravatar: Gravatar
9 | external: External site image
10 | image_url: Image URL
11 | gravatar_email: Gravatar email
12 | description: Description
13 | name: Name
14 |
--------------------------------------------------------------------------------
/config/locales/activerecord.ja.yml:
--------------------------------------------------------------------------------
1 | ja:
2 | activerecord:
3 | attributes:
4 | profile:
5 | atname: アット名
6 | avatar_kinds:
7 | default: デフォルト
8 | gravatar: Gravatar
9 | external: 外部サイトの画像
10 | image_url: 画像URL
11 | gravatar_email: Gravatarのメールアドレス
12 | description: 自己紹介
13 | name: 名前
14 |
--------------------------------------------------------------------------------
/config/locales/errors.en.yml:
--------------------------------------------------------------------------------
1 | en:
2 | errors:
3 | messages:
4 | url: is not a URL
5 |
--------------------------------------------------------------------------------
/config/locales/errors.ja.yml:
--------------------------------------------------------------------------------
1 | ja:
2 | errors:
3 | messages:
4 | url: はURLではありません
5 |
--------------------------------------------------------------------------------
/config/locales/verbs.en.yml:
--------------------------------------------------------------------------------
1 | en:
2 | verbs:
3 | add: Add
4 | add_link_card: "Add link card: %{host_and_path}"
5 | close: Close
6 | connect: Connect
7 | copy_link_to_post: Copy link to post
8 | copy_link_to_profile: Copy link to profile
9 | delete: Delete
10 | disconnect: Disconnect
11 | follow: Follow
12 | hide: Hide
13 | post: Post
14 | search: Search
15 | sign_in: Sign in
16 | sign_up: Create account
17 | submit: Submit
18 | update: Update
19 |
--------------------------------------------------------------------------------
/config/locales/verbs.ja.yml:
--------------------------------------------------------------------------------
1 | ja:
2 | verbs:
3 | add: 追加する
4 | add_link_card: "リンクカードを追加する: %{host_and_path}"
5 | close: 閉じる
6 | connect: 連携する
7 | copy_link_to_post: ポストへのリンクをコピー
8 | copy_link_to_profile: プロフィールへのリンクをコピー
9 | delete: 削除する
10 | disconnect: 連携解除する
11 | follow: フォローする
12 | hide: 非表示にする
13 | post: 投稿する
14 | search: 検索する
15 | sign_in: ログインする
16 | sign_up: アカウントを作成する
17 | submit: 送信する
18 | update: 更新する
19 |
--------------------------------------------------------------------------------
/config/mewst.yml:
--------------------------------------------------------------------------------
1 | shared:
2 | community_url: <%= ENV["MEWST_COMMUNITY_URL"] %>
3 | email_domain: <%= ENV["MEWST_EMAIL_DOMAIN"] %>
4 | privacy_url: <%= ENV["MEWST_PRIVACY_URL"] %>
5 | resend_api_key: <%= ENV["MEWST_RESEND_API_KEY"] %>
6 | reserved_atnames:
7 | - admin
8 | - administrator
9 | - administrators
10 | - admins
11 | - atname
12 | - example
13 | - me
14 | - official
15 | - self
16 | sentry_dsn: <%= ENV["MEWST_SENTRY_DSN"] %>
17 | sign_up_stopper_enabled: <%= ENV["MEWST_SIGN_UP_STOPPER_ENABLED"] %>
18 | terms_url: <%= ENV["MEWST_TERMS_URL"] %>
19 | url: <%= ENV["MEWST_URL"] %>
20 |
--------------------------------------------------------------------------------
/db/migrate/20231015050126_add_time_zone_to_users.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class AddTimeZoneToUsers < ActiveRecord::Migration[7.0]
4 | def change
5 | add_column :users, :time_zone, :string, null: false, default: "Etc/UTC"
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20231025165318_add_discarded_at_to_posts_and_profiles.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class AddDiscardedAtToPostsAndProfiles < ActiveRecord::Migration[7.0]
4 | disable_ddl_transaction!
5 |
6 | def change
7 | %i[posts profiles].each do |table_name|
8 | add_column table_name, :discarded_at, :datetime
9 | add_index table_name, :discarded_at, algorithm: :concurrently
10 | end
11 |
12 | safety_assured do
13 | remove_column :profiles, :deleted_at # standard:disable Rails/ReversibleMigration
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/db/migrate/20231107174301_rename_comment_to_content_on_posts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class RenameCommentToContentOnPosts < ActiveRecord::Migration[7.0]
4 | def change
5 | StrongMigrations.disable_check(:rename_column)
6 | rename_column :posts, :comment, :content
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/db/migrate/20231112022226_add_last_post_at_to_profiles.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class AddLastPostAtToProfiles < ActiveRecord::Migration[7.0]
4 | disable_ddl_transaction!
5 |
6 | def change
7 | add_column :profiles, :last_post_at, :datetime
8 | add_index :profiles, :last_post_at, algorithm: :concurrently
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20231113161740_add_via_id_to_posts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class AddViaIdToPosts < ActiveRecord::Migration[7.0]
4 | disable_ddl_transaction!
5 |
6 | def change
7 | add_column :posts, :oauth_application_id, :uuid
8 | add_index :posts, :oauth_application_id, algorithm: :concurrently
9 | add_foreign_key :posts, :oauth_applications, column: :oauth_application_id, validate: false
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20231113162310_add_validation_via_id_to_posts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class AddValidationViaIdToPosts < ActiveRecord::Migration[7.0]
4 | def change
5 | validate_foreign_key :posts, :oauth_applications
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20231115145714_add_null_false_to_oauth_application_id_on_posts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class AddNullFalseToOauthApplicationIdOnPosts < ActiveRecord::Migration[7.0]
4 | def change
5 | StrongMigrations.disable_check(:change_column_null_postgresql)
6 | change_column_null :posts, :oauth_application_id, false
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/db/migrate/20231115172238_change_email_columns_to_citext.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class ChangeEmailColumnsToCitext < ActiveRecord::Migration[7.0]
4 | def change
5 | StrongMigrations.disable_check(:change_column)
6 | # standard:disable Rails/ReversibleMigration
7 | change_column :email_confirmations, :email, :citext
8 | change_column :users, :email, :citext
9 | # standard:enable Rails/ReversibleMigration
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20231216042900_drop_follow_notifications.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class DropFollowNotifications < ActiveRecord::Migration[7.1]
4 | def change
5 | drop_table :follow_notifications # standard:disable Rails/ReversibleMigration
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20240115144958_create_good_job_settings.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class CreateGoodJobSettings < ActiveRecord::Migration[7.1]
4 | def change
5 | reversible do |dir|
6 | dir.up do
7 | # Ensure this incremental update migration is idempotent
8 | # with monolithic install migration.
9 | return if connection.table_exists?(:good_job_settings)
10 | end
11 | end
12 |
13 | create_table :good_job_settings, id: :uuid do |t|
14 | t.timestamps
15 | t.text :key
16 | t.jsonb :value
17 | t.index :key, unique: true
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/db/migrate/20240115144962_create_good_jobs_error_event.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class CreateGoodJobsErrorEvent < ActiveRecord::Migration[7.1]
4 | def change
5 | reversible do |dir|
6 | dir.up do
7 | # Ensure this incremental update migration is idempotent
8 | # with monolithic install migration.
9 | return if connection.column_exists?(:good_jobs, :error_event)
10 | end
11 | end
12 |
13 | add_column :good_jobs, :error_event, :integer, limit: 2
14 | add_column :good_job_executions, :error_event, :integer, limit: 2
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/db/migrate/20240115144964_create_good_job_labels.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class CreateGoodJobLabels < ActiveRecord::Migration[7.1]
4 | def change
5 | reversible do |dir|
6 | dir.up do
7 | # Ensure this incremental update migration is idempotent
8 | # with monolithic install migration.
9 | return if connection.column_exists?(:good_jobs, :labels)
10 | end
11 | end
12 |
13 | add_column :good_jobs, :labels, :text, array: true
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20240324094358_create_home_timeline_posts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class CreateHomeTimelinePosts < ActiveRecord::Migration[7.1]
4 | def change
5 | create_table :home_timeline_posts, id: false do |t|
6 | t.uuid :id, default: "generate_ulid()", null: false, primary_key: true
7 | t.references :profile, foreign_key: true, null: false, type: :uuid
8 | t.references :post, foreign_key: true, null: false, type: :uuid
9 | t.datetime :published_at, null: false
10 |
11 | t.index %i[profile_id post_id], unique: true
12 | t.index :published_at
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20240403174827_create_sessions.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class CreateSessions < ActiveRecord::Migration[7.1]
4 | def change
5 | create_table :sessions, id: false do |t|
6 | t.uuid :id, default: "generate_ulid()", null: false, primary_key: true
7 | t.references :actor, foreign_key: true, null: false, type: :uuid
8 | t.string :token, index: {unique: true}, null: false
9 | t.string :ip_address, default: "", null: false
10 | t.string :user_agent, default: "", null: false
11 | t.datetime :signed_in_at, null: false
12 | t.timestamps
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/db/migrate/20240404162020_remove_sign_in_columns_on_users.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class RemoveSignInColumnsOnUsers < ActiveRecord::Migration[7.1]
4 | def change
5 | safety_assured do
6 | remove_column :users, :sign_in_count, :integer
7 | remove_column :users, :current_signed_in_at, :datetime
8 | remove_column :users, :last_signed_in_at, :datetime
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20240414152059_remove_stamps_count_on_posts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class RemoveStampsCountOnPosts < ActiveRecord::Migration[7.1]
4 | def change
5 | safety_assured do
6 | remove_column :posts, :stamps_count, :integer
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20240414155158_create_links.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class CreateLinks < ActiveRecord::Migration[7.1]
4 | def change
5 | create_table :links, id: false do |t|
6 | t.uuid :id, default: "generate_ulid()", null: false, primary_key: true
7 | t.string :canonical_url, index: {unique: true}, null: false
8 | t.string :domain, null: false
9 | t.string :title, null: false
10 | t.string :image_url, default: "", null: false
11 | t.timestamps
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/db/migrate/20240414155325_create_post_links.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class CreatePostLinks < ActiveRecord::Migration[7.1]
4 | def change
5 | create_table :post_links, id: false do |t|
6 | t.uuid :id, default: "generate_ulid()", null: false, primary_key: true
7 | t.references :post, foreign_key: true, null: false, type: :uuid
8 | t.references :link, foreign_key: true, null: false, type: :uuid
9 | t.timestamps
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/20240422190022_fix_notifications_for_delegated_type.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class FixNotificationsForDelegatedType < ActiveRecord::Migration[7.1]
4 | def change
5 | add_column :notifications, :notifiable_id, :uuid, null: false
6 | drop_table :stamp_notifications # rubocop:disable Rails/ReversibleMigration
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/db/migrate/20240427202315_add_gravatar_url_to_profiles.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | class AddGravatarUrlToProfiles < ActiveRecord::Migration[7.1]
4 | def change
5 | StrongMigrations.disable_check(:rename_column)
6 | rename_column :profiles, :avatar_url, :image_url
7 |
8 | safety_assured do
9 | change_table :profiles, bulk: true do |t|
10 | t.string :gravatar_email, default: "", null: false
11 | t.string :gravatar_url, default: "", null: false
12 | t.string :avatar_kind, default: "default", null: false
13 | end
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | OauthApplication.where(uid: OauthApplication::MEWST_WEB_UID).first_or_create!(
4 | name: "Mewst for Web",
5 | redirect_uri: "https://example.com/callback",
6 | scopes: ""
7 | )
8 |
--------------------------------------------------------------------------------
/lib/mewst/ui/base.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Mewst::UI::Base < ViewComponent::Base
5 | extend T::Sig
6 | end
7 |
--------------------------------------------------------------------------------
/lib/mewst/ui/button.html.erb:
--------------------------------------------------------------------------------
1 | <%= content_tag(as, class: class_names(class_name).presence, **options) do %>
2 | <%= content %>
3 | <% end %>
4 |
--------------------------------------------------------------------------------
/lib/mewst/ui/button.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Mewst::UI::Button < Mewst::UI::Base
5 | sig { params(as: Symbol, class_name: String, options: T::Hash[Symbol, T.anything]).void }
6 | def initialize(as: :button, class_name: "", **options)
7 | @as = as
8 | @class_name = class_name
9 | @options = options
10 | end
11 |
12 | sig { returns(Symbol) }
13 | attr_reader :as
14 | private :as
15 |
16 | sig { returns(String) }
17 | attr_reader :class_name
18 | private :class_name
19 |
20 | sig { returns(T::Hash[Symbol, T.anything]) }
21 | attr_reader :options
22 | private :options
23 | end
24 |
--------------------------------------------------------------------------------
/lib/mewst/ui/card.html.erb:
--------------------------------------------------------------------------------
1 | <%= tag.div(class: class_names("bg-base-300 card", class_name)) do %>
2 | <%= content %>
3 | <% end %>
4 |
--------------------------------------------------------------------------------
/lib/mewst/ui/card.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Mewst::UI::Card < Mewst::UI::Base
5 | sig { params(class_name: String).void }
6 | def initialize(class_name: "")
7 | @class_name = class_name
8 | end
9 |
10 | sig { returns(String) }
11 | attr_reader :class_name
12 | private :class_name
13 | end
14 |
--------------------------------------------------------------------------------
/lib/mewst/ui/card/body.html.erb:
--------------------------------------------------------------------------------
1 | <%= tag.div(class: class_names("card-body p-4", class_name)) do %>
2 | <%= content %>
3 | <% end %>
4 |
--------------------------------------------------------------------------------
/lib/mewst/ui/card/body.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Mewst::UI::Card::Body < Mewst::UI::Base
5 | sig { params(class_name: String).void }
6 | def initialize(class_name: "")
7 | @class_name = class_name
8 | end
9 |
10 | sig { returns(String) }
11 | attr_reader :class_name
12 | private :class_name
13 | end
14 |
--------------------------------------------------------------------------------
/lib/mewst/ui/dropdown.html.erb:
--------------------------------------------------------------------------------
1 | "
3 | data-action="keydown.esc->dropdown#close"
4 | data-controller="dropdown"
5 | >
6 | <%= content %>
7 |
8 |
--------------------------------------------------------------------------------
/lib/mewst/ui/dropdown.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Mewst::UI::Dropdown < Mewst::UI::Base
5 | sig { params(class_name: String).void }
6 | def initialize(class_name: "")
7 | @class_name = class_name
8 | end
9 |
10 | sig { returns(String) }
11 | attr_reader :class_name
12 | private :class_name
13 | end
14 |
--------------------------------------------------------------------------------
/lib/mewst/ui/dropdown/button.html.erb:
--------------------------------------------------------------------------------
1 |
5 | <%= content %>
6 |
7 |
--------------------------------------------------------------------------------
/lib/mewst/ui/dropdown/button.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Mewst::UI::Dropdown::Button < Mewst::UI::Base
5 | sig { params(class_name: String).void }
6 | def initialize(class_name: "")
7 | @class_name = class_name
8 | end
9 |
10 | sig { returns(String) }
11 | attr_reader :class_name
12 | private :class_name
13 | end
14 |
--------------------------------------------------------------------------------
/lib/mewst/ui/dropdown/item.html.erb:
--------------------------------------------------------------------------------
1 | <%= tag.li(
2 | class: class_names(class_name).presence
3 | ) do %>
4 | <%= content %>
5 | <% end %>
6 |
--------------------------------------------------------------------------------
/lib/mewst/ui/dropdown/item.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Mewst::UI::Dropdown::Item < Mewst::UI::Base
5 | sig { params(class_name: String).void }
6 | def initialize(class_name: "")
7 | @class_name = class_name
8 | end
9 |
10 | sig { returns(String) }
11 | attr_reader :class_name
12 | private :class_name
13 | end
14 |
--------------------------------------------------------------------------------
/lib/mewst/ui/dropdown/list.html.erb:
--------------------------------------------------------------------------------
1 | "
3 | data-dropdown-target="list"
4 | >
5 | <%= content %>
6 |
7 |
--------------------------------------------------------------------------------
/lib/mewst/ui/dropdown/list.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Mewst::UI::Dropdown::List < Mewst::UI::Base
5 | sig { params(class_name: String).void }
6 | def initialize(class_name: "")
7 | @class_name = class_name
8 | end
9 |
10 | sig { returns(String) }
11 | attr_reader :class_name
12 | private :class_name
13 | end
14 |
--------------------------------------------------------------------------------
/lib/mewst/ui/icon.html.erb:
--------------------------------------------------------------------------------
1 | <%= inline_svg_tag("icons/#{name}.svg", {
2 | class: icon_class_name,
3 | size:,
4 | }) %>
5 |
--------------------------------------------------------------------------------
/lib/mewst/ui/tabs.html.erb:
--------------------------------------------------------------------------------
1 | <%= tag.div(
2 | class: class_names("tabs tabs-bordered", class_name),
3 | role: "tablist"
4 | ) do %>
5 | <% items.each do |item| %>
6 | <%= item %>
7 | <% end %>
8 | <% end %>
9 |
--------------------------------------------------------------------------------
/lib/mewst/ui/tabs.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Mewst::UI::Tabs < Mewst::UI::Base
5 | renders_many :items, Mewst::UI::Tabs::Item
6 |
7 | sig { params(class_name: String).void }
8 | def initialize(class_name: "")
9 | @class_name = class_name
10 | end
11 |
12 | sig { returns(String) }
13 | attr_reader :class_name
14 | private :class_name
15 | end
16 |
--------------------------------------------------------------------------------
/lib/mewst/ui/tabs/item.html.erb:
--------------------------------------------------------------------------------
1 | <%= tag.a(
2 | class: class_names("font-semibold h-12 tab", class_name, "tab-active": active, "text-gray-500": !active),
3 | href:,
4 | role: "tab"
5 | ) do %>
6 | <%= content %>
7 | <% end %>
8 |
--------------------------------------------------------------------------------
/lib/mewst/ui/tabs/item.rb:
--------------------------------------------------------------------------------
1 | # typed: strict
2 | # frozen_string_literal: true
3 |
4 | class Mewst::UI::Tabs::Item < Mewst::UI::Base
5 | sig { params(href: String, active: T::Boolean, class_name: String).void }
6 | def initialize(href:, active: false, class_name: "")
7 | @href = href
8 | @active = active
9 | @class_name = class_name
10 | end
11 |
12 | sig { returns(String) }
13 | attr_reader :href
14 | private :href
15 |
16 | sig { returns(T::Boolean) }
17 | attr_reader :active
18 | private :active
19 |
20 | sig { returns(String) }
21 | attr_reader :class_name
22 | private :class_name
23 | end
24 |
--------------------------------------------------------------------------------
/lib/tasks/sorbet.rake:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | namespace :sorbet do
5 | task update: :environment do
6 | system "bin/tapioca gem"
7 | system "bin/tapioca dsl"
8 | system "bin/tapioca todo"
9 | system "bin/tapioca annotations"
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/lib/tasks/suggested_follow.rake:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | namespace :suggested_follow do
5 | desc "おすすめプロフィールを作成する"
6 | task create: :environment do
7 | # Note: limitに指定している数値に深い意味はない
8 | Profile.kept.sort_by_latest_post.limit(1_000).each do |source_profile|
9 | CreateSuggestedFollowsUseCase.new.call(source_profile:)
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mewstcom/mewst/3ac44bfbed0978ba6e61d5ca44658ea91323379c/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mewstcom/mewst/3ac44bfbed0978ba6e61d5ca44658ea91323379c/public/favicon.ico
--------------------------------------------------------------------------------
/public/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mewstcom/mewst/3ac44bfbed0978ba6e61d5ca44658ea91323379c/public/icon-192.png
--------------------------------------------------------------------------------
/public/icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mewstcom/mewst/3ac44bfbed0978ba6e61d5ca44658ea91323379c/public/icon-512.png
--------------------------------------------------------------------------------
/public/og-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mewstcom/mewst/3ac44bfbed0978ba6e61d5ca44658ea91323379c/public/og-image.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 |
--------------------------------------------------------------------------------
/sorbet/config:
--------------------------------------------------------------------------------
1 | --dir
2 | .
3 | --ignore=vendor/
4 |
--------------------------------------------------------------------------------
/sorbet/rbi/annotations/.gitattributes:
--------------------------------------------------------------------------------
1 | **/*.rbi linguist-vendored=true
2 |
--------------------------------------------------------------------------------
/sorbet/rbi/annotations/actionmailer.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This file was pulled from a central RBI files repository.
5 | # Please run `bin/tapioca annotations` to update it.
6 |
7 | class ActionMailer::Base
8 | sig { params(headers: T.untyped, block: T.nilable(T.proc.params(arg0: ActionMailer::Collector).void)).returns(Mail::Message) }
9 | def mail(headers = nil, &block); end
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/annotations/faraday.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This file was pulled from a central RBI files repository.
5 | # Please run `bin/tapioca annotations` to update it.
6 |
7 | module Faraday
8 | class << self
9 | sig { params(url: T.untyped, options: T::Hash[Symbol, T.untyped], block: T.nilable(T.proc.params(connection: Faraday::Connection).void)).returns(Faraday::Connection) }
10 | def new(url = nil, options = {}, &block); end
11 | end
12 | end
13 |
14 | class Faraday::Response
15 | sig { returns(T::Boolean) }
16 | def success?; end
17 | end
18 |
--------------------------------------------------------------------------------
/sorbet/rbi/annotations/pundit.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This file was pulled from a central RBI files repository.
5 | # Please run `bin/tapioca annotations` to update it.
6 |
7 | module Pundit::Authorization
8 | sig { void }
9 | def skip_authorization; end
10 |
11 | sig { void }
12 | def skip_policy_scope; end
13 | end
14 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/.gitattributes:
--------------------------------------------------------------------------------
1 | **/*.rbi linguist-generated=true
2 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/abstract_controller/rendering.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `AbstractController::Rendering`.
5 | # Please instead update this file by running `bin/tapioca dsl AbstractController::Rendering`.
6 |
7 |
8 | module AbstractController::Rendering
9 | mixes_in_class_methods ::ActionView::ViewPaths::ClassMethods
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_controller/api_rendering.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionController::ApiRendering`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionController::ApiRendering`.
6 |
7 |
8 | module ActionController::ApiRendering
9 | mixes_in_class_methods ::ActionView::ViewPaths::ClassMethods
10 | mixes_in_class_methods ::ActionView::Rendering::ClassMethods
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_controller/data_streaming.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionController::DataStreaming`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionController::DataStreaming`.
6 |
7 |
8 | module ActionController::DataStreaming
9 | mixes_in_class_methods ::ActionController::Rendering::ClassMethods
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_controller/flash.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionController::Flash`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionController::Flash`.
6 |
7 |
8 | module ActionController::Flash
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def _flash_types; end
15 | def _flash_types=(value); end
16 | def _flash_types?; end
17 | end
18 |
19 | module GeneratedInstanceMethods; end
20 | end
21 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_controller/form_builder.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionController::FormBuilder`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionController::FormBuilder`.
6 |
7 |
8 | module ActionController::FormBuilder
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def _default_form_builder; end
15 | def _default_form_builder=(value); end
16 | def _default_form_builder?; end
17 | end
18 |
19 | module GeneratedInstanceMethods; end
20 | end
21 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_dispatch/assertions.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionDispatch::Assertions`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionDispatch::Assertions`.
6 |
7 |
8 | module ActionDispatch::Assertions
9 | mixes_in_class_methods ::ActionDispatch::Assertions::RoutingAssertions::ClassMethods
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_dispatch/integration_test.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionDispatch::IntegrationTest`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionDispatch::IntegrationTest`.
6 |
7 |
8 | class ActionDispatch::IntegrationTest
9 | include GeneratedUrlHelpersModule
10 | include GeneratedPathHelpersModule
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_mailer/callbacks.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionMailer::Callbacks`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionMailer::Callbacks`.
6 |
7 |
8 | module ActionMailer::Callbacks
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def __callbacks; end
15 | def __callbacks=(value); end
16 | def __callbacks?; end
17 | end
18 |
19 | module GeneratedInstanceMethods
20 | def __callbacks; end
21 | def __callbacks?; end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_mailer/form_builder.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionMailer::FormBuilder`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionMailer::FormBuilder`.
6 |
7 |
8 | module ActionMailer::FormBuilder
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def _default_form_builder; end
15 | def _default_form_builder=(value); end
16 | def _default_form_builder?; end
17 | end
18 |
19 | module GeneratedInstanceMethods; end
20 | end
21 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_view/helpers.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionView::Helpers`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionView::Helpers`.
6 |
7 |
8 | module ActionView::Helpers
9 | include GeneratedUrlHelpersModule
10 | include GeneratedPathHelpersModule
11 |
12 | mixes_in_class_methods ::ActionView::Helpers::UrlHelper::ClassMethods
13 | mixes_in_class_methods ::ActionView::Helpers::SanitizeHelper::ClassMethods
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_view/helpers/form_helper.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionView::Helpers::FormHelper`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionView::Helpers::FormHelper`.
6 |
7 |
8 | module ActionView::Helpers::FormHelper
9 | mixes_in_class_methods ::ActionView::Helpers::UrlHelper::ClassMethods
10 | mixes_in_class_methods ::ActionView::Helpers::SanitizeHelper::ClassMethods
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_view/helpers/form_tag_helper.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionView::Helpers::FormTagHelper`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionView::Helpers::FormTagHelper`.
6 |
7 |
8 | module ActionView::Helpers::FormTagHelper
9 | mixes_in_class_methods ::ActionView::Helpers::UrlHelper::ClassMethods
10 | mixes_in_class_methods ::ActionView::Helpers::SanitizeHelper::ClassMethods
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_view/helpers/text_helper.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionView::Helpers::TextHelper`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionView::Helpers::TextHelper`.
6 |
7 |
8 | module ActionView::Helpers::TextHelper
9 | mixes_in_class_methods ::ActionView::Helpers::SanitizeHelper::ClassMethods
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/action_view/rendering.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActionView::Rendering`.
5 | # Please instead update this file by running `bin/tapioca dsl ActionView::Rendering`.
6 |
7 |
8 | module ActionView::Rendering
9 | mixes_in_class_methods ::ActionView::ViewPaths::ClassMethods
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/active_job/logging.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActiveJob::Logging`.
5 | # Please instead update this file by running `bin/tapioca dsl ActiveJob::Logging`.
6 |
7 |
8 | module ActiveJob::Logging
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def log_arguments; end
15 | def log_arguments=(value); end
16 | def log_arguments?; end
17 | end
18 |
19 | module GeneratedInstanceMethods; end
20 | end
21 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/active_job/queue_adapter.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActiveJob::QueueAdapter`.
5 | # Please instead update this file by running `bin/tapioca dsl ActiveJob::QueueAdapter`.
6 |
7 |
8 | module ActiveJob::QueueAdapter
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def _queue_adapter; end
15 | def _queue_adapter=(value); end
16 | def _queue_adapter_name; end
17 | def _queue_adapter_name=(value); end
18 | end
19 |
20 | module GeneratedInstanceMethods; end
21 | end
22 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/active_job/queue_priority.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActiveJob::QueuePriority`.
5 | # Please instead update this file by running `bin/tapioca dsl ActiveJob::QueuePriority`.
6 |
7 |
8 | module ActiveJob::QueuePriority
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def priority; end
15 | def priority=(value); end
16 | def priority?; end
17 | end
18 |
19 | module GeneratedInstanceMethods; end
20 | end
21 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/active_job/test_helper/test_queue_adapter.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActiveJob::TestHelper::TestQueueAdapter`.
5 | # Please instead update this file by running `bin/tapioca dsl ActiveJob::TestHelper::TestQueueAdapter`.
6 |
7 |
8 | module ActiveJob::TestHelper::TestQueueAdapter
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def _test_adapter; end
15 | def _test_adapter=(value); end
16 | end
17 |
18 | module GeneratedInstanceMethods; end
19 | end
20 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/active_model/conversion.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActiveModel::Conversion`.
5 | # Please instead update this file by running `bin/tapioca dsl ActiveModel::Conversion`.
6 |
7 |
8 | module ActiveModel::Conversion
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def param_delimiter; end
15 | def param_delimiter=(value); end
16 | def param_delimiter?; end
17 | end
18 |
19 | module GeneratedInstanceMethods
20 | def param_delimiter=(value); end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/active_record/counter_cache.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActiveRecord::CounterCache`.
5 | # Please instead update this file by running `bin/tapioca dsl ActiveRecord::CounterCache`.
6 |
7 |
8 | module ActiveRecord::CounterCache
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def _counter_cache_columns; end
15 | def _counter_cache_columns=(value); end
16 | def _counter_cache_columns?; end
17 | end
18 |
19 | module GeneratedInstanceMethods; end
20 | end
21 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/active_record/readonly_attributes.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActiveRecord::ReadonlyAttributes`.
5 | # Please instead update this file by running `bin/tapioca dsl ActiveRecord::ReadonlyAttributes`.
6 |
7 |
8 | module ActiveRecord::ReadonlyAttributes
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def _attr_readonly; end
15 | def _attr_readonly=(value); end
16 | def _attr_readonly?; end
17 | end
18 |
19 | module GeneratedInstanceMethods; end
20 | end
21 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/active_record/secure_password.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ActiveRecord::SecurePassword`.
5 | # Please instead update this file by running `bin/tapioca dsl ActiveRecord::SecurePassword`.
6 |
7 |
8 | module ActiveRecord::SecurePassword
9 | mixes_in_class_methods ::ActiveModel::SecurePassword::ClassMethods
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/api/v1/application_controller.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `Api::V1::ApplicationController`.
5 | # Please instead update this file by running `bin/tapioca dsl Api::V1::ApplicationController`.
6 |
7 |
8 | class Api::V1::ApplicationController
9 | include GeneratedUrlHelpersModule
10 | include GeneratedPathHelpersModule
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/api/v1/internal/application_controller.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `Api::V1::Internal::ApplicationController`.
5 | # Please instead update this file by running `bin/tapioca dsl Api::V1::Internal::ApplicationController`.
6 |
7 |
8 | class Api::V1::Internal::ApplicationController
9 | include GeneratedUrlHelpersModule
10 | include GeneratedPathHelpersModule
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/application_component.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ApplicationComponent`.
5 | # Please instead update this file by running `bin/tapioca dsl ApplicationComponent`.
6 |
7 |
8 | class ApplicationComponent
9 | include GeneratedUrlHelpersModule
10 | include GeneratedPathHelpersModule
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/application_mailer.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ApplicationMailer`.
5 | # Please instead update this file by running `bin/tapioca dsl ApplicationMailer`.
6 |
7 |
8 | class ApplicationMailer
9 | include GeneratedUrlHelpersModule
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/delete_post_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `DeletePostForm`.
5 | # Please instead update this file by running `bin/tapioca dsl DeletePostForm`.
6 |
7 |
8 | class DeletePostForm
9 | sig { returns(T.nilable(::String)) }
10 | def target_post_id; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def target_post_id=(value); end
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/discard_post_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `DiscardPostForm`.
5 | # Please instead update this file by running `bin/tapioca dsl DiscardPostForm`.
6 |
7 |
8 | class DiscardPostForm
9 | sig { returns(T.nilable(::String)) }
10 | def target_post_id; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def target_post_id=(value); end
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/doorkeeper/access_grant_mixin.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `Doorkeeper::AccessGrantMixin`.
5 | # Please instead update this file by running `bin/tapioca dsl Doorkeeper::AccessGrantMixin`.
6 |
7 |
8 | module Doorkeeper::AccessGrantMixin
9 | mixes_in_class_methods ::Doorkeeper::Models::Orderable::ClassMethods
10 | mixes_in_class_methods ::Doorkeeper::Models::SecretStorable::ClassMethods
11 | mixes_in_class_methods ::Doorkeeper::Models::ResourceOwnerable::ClassMethods
12 | end
13 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/doorkeeper/access_token_mixin.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `Doorkeeper::AccessTokenMixin`.
5 | # Please instead update this file by running `bin/tapioca dsl Doorkeeper::AccessTokenMixin`.
6 |
7 |
8 | module Doorkeeper::AccessTokenMixin
9 | mixes_in_class_methods ::Doorkeeper::Models::Orderable::ClassMethods
10 | mixes_in_class_methods ::Doorkeeper::Models::SecretStorable::ClassMethods
11 | mixes_in_class_methods ::Doorkeeper::Models::ResourceOwnerable::ClassMethods
12 | mixes_in_class_methods ::Doorkeeper::Models::ExpirationTimeSqlMath::ClassMethods
13 | end
14 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/doorkeeper/application_controller.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `Doorkeeper::ApplicationController`.
5 | # Please instead update this file by running `bin/tapioca dsl Doorkeeper::ApplicationController`.
6 |
7 |
8 | class Doorkeeper::ApplicationController
9 | include GeneratedUrlHelpersModule
10 | include GeneratedPathHelpersModule
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/doorkeeper/application_metal_controller.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `Doorkeeper::ApplicationMetalController`.
5 | # Please instead update this file by running `bin/tapioca dsl Doorkeeper::ApplicationMetalController`.
6 |
7 |
8 | class Doorkeeper::ApplicationMetalController
9 | include GeneratedUrlHelpersModule
10 | include GeneratedPathHelpersModule
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/doorkeeper/application_mixin.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `Doorkeeper::ApplicationMixin`.
5 | # Please instead update this file by running `bin/tapioca dsl Doorkeeper::ApplicationMixin`.
6 |
7 |
8 | module Doorkeeper::ApplicationMixin
9 | mixes_in_class_methods ::Doorkeeper::Models::Orderable::ClassMethods
10 | mixes_in_class_methods ::Doorkeeper::Models::SecretStorable::ClassMethods
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/email_confirmation_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `EmailConfirmationForm`.
5 | # Please instead update this file by running `bin/tapioca dsl EmailConfirmationForm`.
6 |
7 |
8 | class EmailConfirmationForm
9 | sig { returns(T.nilable(::String)) }
10 | def email; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def email=(value); end
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/email_confirmation_mailer.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `EmailConfirmationMailer`.
5 | # Please instead update this file by running `bin/tapioca dsl EmailConfirmationMailer`.
6 |
7 |
8 | class EmailConfirmationMailer
9 | class << self
10 | sig { params(email_confirmation_id: ::String, locale: ::String).returns(::ActionMailer::MessageDelivery) }
11 | def email_confirmation(email_confirmation_id:, locale:); end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/email_update_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `EmailUpdateForm`.
5 | # Please instead update this file by running `bin/tapioca dsl EmailUpdateForm`.
6 |
7 |
8 | class EmailUpdateForm
9 | sig { returns(T.nilable(::String)) }
10 | def new_email; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def new_email=(value); end
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/fanout_post_job.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `FanoutPostJob`.
5 | # Please instead update this file by running `bin/tapioca dsl FanoutPostJob`.
6 |
7 |
8 | class FanoutPostJob
9 | class << self
10 | sig do
11 | params(
12 | post_id: ::String,
13 | block: T.nilable(T.proc.params(job: FanoutPostJob).void)
14 | ).returns(T.any(FanoutPostJob, FalseClass))
15 | end
16 | def perform_later(post_id:, &block); end
17 |
18 | sig { params(post_id: ::String).void }
19 | def perform_now(post_id:); end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/follow_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `FollowForm`.
5 | # Please instead update this file by running `bin/tapioca dsl FollowForm`.
6 |
7 |
8 | class FollowForm
9 | sig { returns(T.nilable(::String)) }
10 | def target_atname; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def target_atname=(value); end
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/good_job/active_job_extensions/labels.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `GoodJob::ActiveJobExtensions::Labels`.
5 | # Please instead update this file by running `bin/tapioca dsl GoodJob::ActiveJobExtensions::Labels`.
6 |
7 |
8 | module GoodJob::ActiveJobExtensions::Labels
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def good_job_labels; end
15 | def good_job_labels=(value); end
16 | end
17 |
18 | module GeneratedInstanceMethods; end
19 | end
20 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/good_job/active_job_extensions/notify_options.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `GoodJob::ActiveJobExtensions::NotifyOptions`.
5 | # Please instead update this file by running `bin/tapioca dsl GoodJob::ActiveJobExtensions::NotifyOptions`.
6 |
7 |
8 | module GoodJob::ActiveJobExtensions::NotifyOptions
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def good_job_notify; end
15 | def good_job_notify=(value); end
16 | end
17 |
18 | module GeneratedInstanceMethods; end
19 | end
20 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/good_job/frontends_controller.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `GoodJob::FrontendsController`.
5 | # Please instead update this file by running `bin/tapioca dsl GoodJob::FrontendsController`.
6 |
7 |
8 | class GoodJob::FrontendsController
9 | sig { returns(HelperProxy) }
10 | def helpers; end
11 |
12 | module HelperMethods
13 | include ::ActionController::Base::HelperMethods
14 | include ::GoodJob::IconsHelper
15 | include ::GoodJob::ApplicationHelper
16 | end
17 |
18 | class HelperProxy < ::ActionView::Base
19 | include HelperMethods
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/keyword_search_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `KeywordSearchForm`.
5 | # Please instead update this file by running `bin/tapioca dsl KeywordSearchForm`.
6 |
7 |
8 | class KeywordSearchForm
9 | sig { returns(T.nilable(::String)) }
10 | def q; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def q=(value); end
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/link_data_fetcher_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `LinkDataFetcherForm`.
5 | # Please instead update this file by running `bin/tapioca dsl LinkDataFetcherForm`.
6 |
7 |
8 | class LinkDataFetcherForm
9 | sig { returns(T.nilable(::String)) }
10 | def target_url; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def target_url=(value); end
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/mewst/ui/base.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `Mewst::UI::Base`.
5 | # Please instead update this file by running `bin/tapioca dsl Mewst::UI::Base`.
6 |
7 |
8 | class Mewst::UI::Base
9 | include GeneratedUrlHelpersModule
10 | include GeneratedPathHelpersModule
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/password_reset_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `PasswordResetForm`.
5 | # Please instead update this file by running `bin/tapioca dsl PasswordResetForm`.
6 |
7 |
8 | class PasswordResetForm
9 | sig { returns(T.nilable(::String)) }
10 | def password; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def password=(value); end
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/session_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `SessionForm`.
5 | # Please instead update this file by running `bin/tapioca dsl SessionForm`.
6 |
7 |
8 | class SessionForm
9 | sig { returns(T.nilable(::String)) }
10 | def email; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def email=(value); end
14 |
15 | sig { returns(T.nilable(::String)) }
16 | def password; end
17 |
18 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
19 | def password=(value); end
20 | end
21 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/stamp_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `StampForm`.
5 | # Please instead update this file by running `bin/tapioca dsl StampForm`.
6 |
7 |
8 | class StampForm
9 | sig { returns(T.nilable(::String)) }
10 | def target_post_id; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def target_post_id=(value); end
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/suggested_follow_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `SuggestedFollowForm`.
5 | # Please instead update this file by running `bin/tapioca dsl SuggestedFollowForm`.
6 |
7 |
8 | class SuggestedFollowForm
9 | sig { returns(T.nilable(::String)) }
10 | def target_atname; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def target_atname=(value); end
14 | end
15 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/time.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `Time`.
5 | # Please instead update this file by running `bin/tapioca dsl Time`.
6 |
7 |
8 | class Time
9 | class << self
10 | sig { returns(::ActiveSupport::TimeWithZone) }
11 | def current; end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/user_form.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `UserForm`.
5 | # Please instead update this file by running `bin/tapioca dsl UserForm`.
6 |
7 |
8 | class UserForm
9 | sig { returns(T.nilable(::String)) }
10 | def locale; end
11 |
12 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
13 | def locale=(value); end
14 |
15 | sig { returns(T.nilable(::String)) }
16 | def time_zone; end
17 |
18 | sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
19 | def time_zone=(value); end
20 | end
21 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/view_component/preview.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ViewComponent::Preview`.
5 | # Please instead update this file by running `bin/tapioca dsl ViewComponent::Preview`.
6 |
7 |
8 | class ViewComponent::Preview
9 | include GeneratedUrlHelpersModule
10 | include GeneratedPathHelpersModule
11 | end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/dsl/view_component/translatable.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for dynamic methods in `ViewComponent::Translatable`.
5 | # Please instead update this file by running `bin/tapioca dsl ViewComponent::Translatable`.
6 |
7 |
8 | module ViewComponent::Translatable
9 | include GeneratedInstanceMethods
10 |
11 | mixes_in_class_methods GeneratedClassMethods
12 |
13 | module GeneratedClassMethods
14 | def i18n_backend; end
15 | def i18n_backend=(value); end
16 | end
17 |
18 | module GeneratedInstanceMethods
19 | def i18n_backend; end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/.gitattributes:
--------------------------------------------------------------------------------
1 | **/*.rbi linguist-generated=true
2 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/actioncable@7.1.5.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `actioncable` gem.
5 | # Please instead update this file by running `bin/tapioca gem actioncable`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/actionmailbox@7.1.5.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `actionmailbox` gem.
5 | # Please instead update this file by running `bin/tapioca gem actionmailbox`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/actiontext@7.1.5.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `actiontext` gem.
5 | # Please instead update this file by running `bin/tapioca gem actiontext`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/activestorage@7.1.5.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `activestorage` gem.
5 | # Please instead update this file by running `bin/tapioca gem activestorage`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/better_html@2.1.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `better_html` gem.
5 | # Please instead update this file by running `bin/tapioca gem better_html`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/bindex@0.8.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `bindex` gem.
5 | # Please instead update this file by running `bin/tapioca gem bindex`.
6 |
7 | # THIS IS AN EMPTY RBI FILE.
8 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
9 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/builder@3.3.0.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `builder` gem.
5 | # Please instead update this file by running `bin/tapioca gem builder`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/crass@1.0.6.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `crass` gem.
5 | # Please instead update this file by running `bin/tapioca gem crass`.
6 |
7 | # THIS IS AN EMPTY RBI FILE.
8 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
9 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/csv@3.3.0.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `csv` gem.
5 | # Please instead update this file by running `bin/tapioca gem csv`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/cuprite@0.15.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `cuprite` gem.
5 | # Please instead update this file by running `bin/tapioca gem cuprite`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/dotenv-rails@3.1.2.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `dotenv-rails` gem.
5 | # Please instead update this file by running `bin/tapioca gem dotenv-rails`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/erb_lint@0.9.0.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `erb_lint` gem.
5 | # Please instead update this file by running `bin/tapioca gem erb_lint`.
6 |
7 |
8 | # source://erb_lint//lib/erb_lint/version.rb#3
9 | module ERBLint; end
10 |
11 | # source://erb_lint//lib/erb_lint/version.rb#4
12 | ERBLint::VERSION = T.let(T.unsafe(nil), String)
13 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/ferrum@0.15.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `ferrum` gem.
5 | # Please instead update this file by running `bin/tapioca gem ferrum`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/ffi@1.16.3.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `ffi` gem.
5 | # Please instead update this file by running `bin/tapioca gem ffi`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/io-console@0.8.0.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `io-console` gem.
5 | # Please instead update this file by running `bin/tapioca gem io-console`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/marcel@1.0.4.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `marcel` gem.
5 | # Please instead update this file by running `bin/tapioca gem marcel`.
6 |
7 | # THIS IS AN EMPTY RBI FILE.
8 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
9 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/method_source@1.1.0.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `method_source` gem.
5 | # Please instead update this file by running `bin/tapioca gem method_source`.
6 |
7 | # THIS IS AN EMPTY RBI FILE.
8 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
9 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/multi_xml@0.7.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `multi_xml` gem.
5 | # Please instead update this file by running `bin/tapioca gem multi_xml`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/net-pop@0.1.2.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `net-pop` gem.
5 | # Please instead update this file by running `bin/tapioca gem net-pop`.
6 |
7 | # THIS IS AN EMPTY RBI FILE.
8 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
9 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/rails@7.1.5.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `rails` gem.
5 | # Please instead update this file by running `bin/tapioca gem rails`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/rails_autolink@1.1.8.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `rails_autolink` gem.
5 | # Please instead update this file by running `bin/tapioca gem rails_autolink`.
6 |
7 | # source://rails_autolink//lib/rails_autolink.rb#1
8 | module RailsAutolink; end
9 |
10 | # source://rails_autolink//lib/rails_autolink.rb#2
11 | class RailsAutolink::Railtie < ::Rails::Railtie; end
12 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/rb-fsevent@0.11.2.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `rb-fsevent` gem.
5 | # Please instead update this file by running `bin/tapioca gem rb-fsevent`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/rb-inotify@0.10.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `rb-inotify` gem.
5 | # Please instead update this file by running `bin/tapioca gem rb-inotify`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/reline@0.6.0.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `reline` gem.
5 | # Please instead update this file by running `bin/tapioca gem reline`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/rspec-core@3.13.2.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `rspec-core` gem.
5 | # Please instead update this file by running `bin/tapioca gem rspec-core`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/rspec-mocks@3.13.2.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `rspec-mocks` gem.
5 | # Please instead update this file by running `bin/tapioca gem rspec-mocks`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/rubocop-performance@1.22.1.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `rubocop-performance` gem.
5 | # Please instead update this file by running `bin/tapioca gem rubocop-performance`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/rubocop-rails@2.25.0.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `rubocop-rails` gem.
5 | # Please instead update this file by running `bin/tapioca gem rubocop-rails`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/smart_properties@1.17.0.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `smart_properties` gem.
5 | # Please instead update this file by running `bin/tapioca gem smart_properties`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/standard-custom@1.0.2.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `standard-custom` gem.
5 | # Please instead update this file by running `bin/tapioca gem standard-custom`.
6 |
7 | # THIS IS AN EMPTY RBI FILE.
8 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
9 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/standard-performance@1.5.0.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `standard-performance` gem.
5 | # Please instead update this file by running `bin/tapioca gem standard-performance`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/stringio@3.1.2.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `stringio` gem.
5 | # Please instead update this file by running `bin/tapioca gem stringio`.
6 |
7 |
8 | # THIS IS AN EMPTY RBI FILE.
9 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/websocket-driver@0.7.6.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `websocket-driver` gem.
5 | # Please instead update this file by running `bin/tapioca gem websocket-driver`.
6 |
7 | # THIS IS AN EMPTY RBI FILE.
8 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
9 |
--------------------------------------------------------------------------------
/sorbet/rbi/gems/websocket-extensions@0.1.5.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | # DO NOT EDIT MANUALLY
4 | # This is an autogenerated file for types exported from the `websocket-extensions` gem.
5 | # Please instead update this file by running `bin/tapioca gem websocket-extensions`.
6 |
7 | # THIS IS AN EMPTY RBI FILE.
8 | # see https://github.com/Shopify/tapioca#manually-requiring-parts-of-a-gem
9 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/account.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Account
5 | def self.enumerize(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/active_record/relation.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class ActiveRecord::Relation
5 | def arel_table
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/addressable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Addressable::URI; end
5 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/api/v1/application_controller.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class V1::ApplicationController
5 | end
6 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/api/v1/form_errorable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::V1::FormErrorable
5 | def render(*args)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/api/v1/timeline/show_controller.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class V1::Timeline::ShowController
5 | end
6 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/application_helper.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ApplicationHelper
5 | def display_meta_tags(*args)
6 | end
7 |
8 | def meta_tags
9 | end
10 |
11 | def request
12 | end
13 |
14 | def t(*args)
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/commented_repost.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class CommentedRepost
5 | def self.counter_culture(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/component_data_fetcher_helper.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ComponentDataFetcherHelper
5 | def tag; end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/controller_concerns/api/authenticatable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::Api::Authenticatable
5 | def self.before_action(*args)
6 | end
7 |
8 | def doorkeeper_token
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/controller_concerns/authenticatable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::Authenticatable
5 | def self.helper_method(*args)
6 | end
7 |
8 | def cookies
9 | end
10 |
11 | def flash
12 | end
13 |
14 | def home_path
15 | end
16 |
17 | def redirect_to(*args)
18 | end
19 |
20 | def request
21 | end
22 |
23 | def reset_session
24 | end
25 |
26 | def root_path
27 | end
28 |
29 | def session
30 | end
31 |
32 | def t(*args)
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/controller_concerns/authorizable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::Authorizable
5 | def current_viewer!
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/controller_concerns/email_confirmation_findable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::EmailConfirmationFindable
5 | def redirect_to(*args)
6 | end
7 |
8 | def root_path
9 | end
10 |
11 | def session
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/controller_concerns/localizable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::Localizable
5 | def viewer
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/email_confirmation.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class EmailConfirmation
5 | def self.enumerize(*args)
6 | end
7 |
8 | def self.event
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/email_confirmation_mailer.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class EmailConfirmationMailer
5 | def local_url(*args); end
6 | def settings_email_callback_url(*args); end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/faraday.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module Faraday
5 | def self.get(*args)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/flash_toast_helper.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module FlashToastHelper
5 | def tag(*args)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/form/password_validatable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module FormConcerns::PasswordValidatable
5 | def self.validate(*args)
6 | end
7 |
8 | def self.validates(*args)
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/google/cloud/pubsub.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module Google::Cloud::PubSub
5 | def self.new(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/google/cloud/pubsub/credentials.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Google::Cloud::PubSub::Credentials
5 | def self.new(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/google/cloud/pubsub/project.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Google::Cloud::PubSub::Project
5 | def topic(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/google/cloud/pubsub/topic.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Google::Cloud::PubSub::Topic
5 | def publish_async(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/google/cloud/tasks/v2/cloud_tasks/client.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Google::Cloud::Tasks::V2::CloudTasks::Client
5 | def create_task(*args); end
6 | def queue_path(*args); end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/google/cloud/tasks/v2/cloud_tasks/credentials.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Google::Cloud::Tasks::V2::CloudTasks::Credentials
5 | def self.new(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/icons/logo_icon_component.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Icons::LogoIconComponent
5 | def self.erb_template(*args)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/icons/stamped_icon_component.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Icons::StampedIconComponent
5 | def self.erb_template(*args)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/icons/unstamped_icon_component.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Icons::UnstampedIconComponent
5 | def self.erb_template(*args)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/internal_authenticatable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::InternalAuthenticatable
5 | def self.before_action(*args)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/kernel.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module Kernel
5 | sig { returns(T.self_type) }
6 | def not_nil!; end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/language_helper.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module LanguageHelper
5 | def t(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/localizable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ControllerConcerns::Localizable
5 | def current_viewer; end
6 | def http_accept_language; end
7 | def params; end
8 | def session; end
9 | end
10 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/mewst/application.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Mewst::Application
5 | def self.config_for(*args)
6 | end
7 |
8 | def self.r301(*args)
9 | end
10 |
11 | def self.send_file(*args)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/model_concerns/notifiable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module ModelConcerns::Notifiable
5 | def self.has_one(*args)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/nil_class.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class NilClass
5 | sig { returns(T.noreturn) }
6 | def not_nil!; end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/notification.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Notification
5 | def self.enumerize(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/post.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Post
5 | def self.enumerize(*args); end
6 | def kind_comment_post?; end
7 | def kind_repost?; end
8 | end
9 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/post/private_association_relation.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Post::PrivateAssociationRelation
5 | include ActiveRecordCursorPaginate::Extension
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/post/private_relation.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Post::PrivateRelation
5 | include ActiveRecordCursorPaginate::Extension
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/profile.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Profile
5 | def self.enumerize(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/profile/private_relation.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Profile::PrivateRelation
5 | include ActiveRecordCursorPaginate::Extension
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/pubsub/subscribable.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module Pubsub::Subscribable
5 | def authenticate_or_request_with_http_token; end
6 | def params; end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/repost.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Repost
5 | def self.counter_culture(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/session/private_collection_proxy.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class Session::PrivateCollectionProxy
5 | def start!(*args)
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/text_helper.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module TextHelper
5 | def auto_link(*args); end
6 | def simple_format(*args); end
7 | end
8 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/time_helper.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | module TimeHelper
5 | def format(*args)
6 | end
7 |
8 | def time_ago_in_words(*args)
9 | end
10 |
11 | def viewer
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/sorbet/rbi/manual/user.rbi:
--------------------------------------------------------------------------------
1 | # typed: strong
2 | # frozen_string_literal: true
3 |
4 | class User
5 | def self.enumerize(*args); end
6 | end
7 |
--------------------------------------------------------------------------------
/sorbet/rbi/shims/loofah.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | class Loofah::Scrubber; end
4 |
--------------------------------------------------------------------------------
/sorbet/rbi/shims/minitest.rbi:
--------------------------------------------------------------------------------
1 | # typed: true
2 |
3 | class Minitest::Test; end
4 |
--------------------------------------------------------------------------------
/sorbet/rbi/todo.rbi:
--------------------------------------------------------------------------------
1 | # DO NOT EDIT MANUALLY
2 | # This is an autogenerated file for unresolved constants.
3 | # Please instead update this file by running `bin/tapioca todo`.
4 |
5 | # typed: false
6 |
7 | module ::RedisClient::PIDCache::CoreExt; end
8 | module Capybara::Cuprite::Driver; end
9 | module V1::FollowForm; end
10 | module V1::PostForm; end
11 | module V1::StampForm; end
12 |
--------------------------------------------------------------------------------
/sorbet/tapioca/config.yml:
--------------------------------------------------------------------------------
1 | gem:
2 | # Add your `gem` command parameters here:
3 | #
4 | # exclude:
5 | # - gem_name
6 | # doc: true
7 | # workers: 5
8 | dsl:
9 | # Add your `dsl` command parameters here:
10 | #
11 | # exclude:
12 | # - SomeGeneratorName
13 | # workers: 5
14 |
--------------------------------------------------------------------------------
/sorbet/tapioca/require.rb:
--------------------------------------------------------------------------------
1 | # typed: true
2 | # frozen_string_literal: true
3 |
4 | # Add your extra requires here (`bin/tapioca require` can be used to boostrap this list)
5 |
--------------------------------------------------------------------------------
/spec/factories/actor.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | FactoryBot.define do
5 | factory :actor do
6 | user { association :user }
7 | profile { user.profile }
8 |
9 | trait :with_access_token_for_web do
10 | after(:create) do |actor|
11 | application = create(:oauth_application, :mewst_web)
12 | create(:oauth_access_token, application:, resource_owner: actor)
13 | end
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/spec/factories/email_confirmation.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | FactoryBot.define do
5 | factory :email_confirmation do
6 | sequence(:email) { |n| "test-#{n}@example.com" }
7 | event { :sign_up }
8 | sequence(:code) { |n| "00000#{n}" }
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/factories/link.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | FactoryBot.define do
5 | factory :link do
6 | sequence(:canonical_url) { |n| "https://example.com/#{n}" }
7 | domain { "example.com" }
8 | sequence(:title) { |n| "Page Title ##{n}" }
9 | image_url { "https://example.com/image.jpg" }
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/spec/factories/oauth_application.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | FactoryBot.define do
5 | factory :oauth_application do
6 | sequence(:name) { |n| "OAuth App #{n}" }
7 | sequence(:uid) { |n| "oauth-app-#{n}" }
8 | secret { "secret" }
9 | redirect_uri { "https://example.com/callback" }
10 | scopes { "read" }
11 |
12 | trait :mewst_web do
13 | name { "Mewst for Web" }
14 | uid { OauthApplication::MEWST_WEB_UID }
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/spec/factories/oauth_oauth_access_token.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | FactoryBot.define do
5 | factory :oauth_access_token do
6 | resource_owner(factory: :actor)
7 | application(factory: :oauth_application)
8 | sequence(:token) { |n| "token_#{n}" }
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/factories/post.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | FactoryBot.define do
5 | factory :post do
6 | profile
7 | sequence(:content) { |n| "test_#{n}" }
8 | published_at { Time.current }
9 | oauth_application
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/spec/factories/profile.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | FactoryBot.define do
5 | factory :profile do
6 | sequence(:atname) { |n| "test_#{n}" }
7 | owner_type { ProfileOwnerType::User.serialize }
8 | joined_at { Time.current }
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/factories/user.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | FactoryBot.define do
5 | factory :user do
6 | profile { association :profile, owner_type: ProfileOwnerType::User.serialize }
7 | sequence(:email) { |n| "test_#{n}@example.com" }
8 | password { "passw0rd" }
9 | locale { :ja }
10 | time_zone { "Asia/Tokyo" }
11 | signed_up_at { Time.current }
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/requests/sign_in/new_spec.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | RSpec.describe "GET /sign_in", type: :request do
5 | context "ログインしているとき" do
6 | let!(:actor) { FactoryBot.create(:actor) }
7 |
8 | before do
9 | sign_in actor
10 | end
11 |
12 | it "ホーム画面にリダイレクトすること" do
13 | get "/sign_in"
14 |
15 | expect(response).to redirect_to(home_path)
16 | end
17 | end
18 |
19 | context "ログインしていないとき" do
20 | it "ページが表示されること" do
21 | get "/sign_in"
22 |
23 | expect(response.body).to include("ログイン")
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/spec/requests/sign_up/new_spec.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | RSpec.describe "GET /sign_up", type: :request do
5 | context "ログインしているとき" do
6 | let!(:actor) { FactoryBot.create(:actor) }
7 |
8 | before do
9 | sign_in actor
10 | end
11 |
12 | it "ホーム画面にリダイレクトすること" do
13 | get "/sign_up"
14 |
15 | expect(response).to redirect_to(home_path)
16 | end
17 | end
18 |
19 | context "ログインしていないとき" do
20 | it "ページが表示されること" do
21 | get "/sign_up"
22 |
23 | expect(response.body).to include("アカウント作成")
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/spec/requests/welcome/show_spec.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | RSpec.describe "GET /", type: :request do
5 | context "ログインしているとき" do
6 | let!(:actor) { FactoryBot.create(:actor) }
7 |
8 | before do
9 | sign_in actor
10 | end
11 |
12 | it "ホーム画面にリダイレクトすること" do
13 | get "/"
14 |
15 | expect(response).to redirect_to(home_path)
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/spec/support/committee.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | RSpec.configure do |config|
5 | config.include Committee::Rails::Test::Methods
6 | config.add_setting :committee_options
7 | config.committee_options = {
8 | query_hash_key: "rack.request.query_hash",
9 | parse_response_by_content_type: false,
10 | strict_reference_validation: true
11 | }
12 |
13 | config.before :all, api_version: :v1 do
14 | RSpec.configure do |config|
15 | config.committee_options[:schema_path] = Rails.root.join("openapi/v1.yaml").to_s
16 | config.committee_options[:prefix] = "/v1"
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/support/factory_bot.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | RSpec.configure do |config|
5 | config.include FactoryBot::Syntax::Methods
6 | end
7 |
--------------------------------------------------------------------------------
/spec/support/request_helpers.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | module RequestHelpers
5 | def sign_in(actor, password: "passw0rd")
6 | post(sign_in_path, params: {session_form: {email: actor.email, password:}})
7 | expect(cookies[Session::COOKIE_KEY]).not_to be_nil
8 | end
9 | end
10 |
11 | RSpec.configure do |config|
12 | config.include RequestHelpers, type: :request
13 | end
14 |
--------------------------------------------------------------------------------
/spec/support/vcr.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | VCR.configure do |config|
5 | config.cassette_library_dir = "fixtures/vcr_cassettes"
6 | config.hook_into :faraday
7 | end
8 |
--------------------------------------------------------------------------------
/spec/system/welcome/show_spec.rb:
--------------------------------------------------------------------------------
1 | # typed: false
2 | # frozen_string_literal: true
3 |
4 | # GitHub Actionsでのテスト実行時にエラーになるため、一旦スキップする
5 | RSpec.xdescribe "トップページ", type: :system do
6 | it do
7 | visit "/"
8 |
9 | expect(page).to have_content "現在ベータ版です"
10 | end
11 | end
12 |
--------------------------------------------------------------------------------