From b37216bb51c6a51365c5553c3d496cd15fbb7afb Mon Sep 17 00:00:00 2001 From: Justin Adkins Date: Mon, 15 Jan 2024 00:38:09 -0500 Subject: [PATCH 01/24] nuke --- .DS_Store | Bin 0 -> 8196 bytes .browserslistrc | 1 - .dockerignore | 48 - .github/CODEOWNERS | 1 - .github/PULL_REQUEST_TEMPLATE/default.md | 3 - .github/workflows/ci.yaml | 86 - .github/workflows/docker.yaml | 74 - .gitignore | 28 - .rubocop.yml | 19 - .ruby-version | 1 - BRANCH | 1 - CHANGELOG.md | 3 - COMMIT | 1 - Dockerfile | 55 - Gemfile | 73 - Gemfile.lock | 514 -- LICENSE | 661 -- README.md | 21 - Rakefile | 8 - VERSION | 1 - app/assets/config/manifest.js | 2 - app/assets/images/.keep | 0 app/assets/images/logo.png | Bin 696 -> 0 bytes app/assets/stylesheets/actiontext.scss | 36 - app/assets/stylesheets/application.scss | 16 - app/components/sidebar_component.rb | 8 - .../sidebar_component.html.haml | 1 - app/controllers/api/messages_controller.rb | 45 - .../api/notifications_controller.rb | 33 - app/controllers/application_controller.rb | 16 - .../client_environments_controller.rb | 39 - app/controllers/client_uploads_controller.rb | 54 - app/controllers/clients_controller.rb | 69 - app/controllers/concerns/.keep | 0 app/controllers/home_controller.rb | 5 - app/controllers/mailing_topics_controller.rb | 39 - app/controllers/messages_controller.rb | 28 - app/controllers/subscribers_controller.rb | 48 - app/controllers/subscriptions_controller.rb | 29 - app/controllers/templates_controller.rb | 40 - app/controllers/turbo_controller.rb | 20 - app/forms/adhoc_email_form.rb | 77 - app/forms/application_form.rb | 5 - app/helpers/application_helper.rb | 34 - app/helpers/client_uploads_helper.rb | 9 - app/helpers/messages_helper.rb | 66 - app/helpers/subscriptions_helper.rb | 9 - app/javascript/application.js | 15 - .../controllers/sidebar_controller.js | 11 - app/javascript/importmap.json.erb | 5 - app/javascript/packs/main.js | 14 - app/jobs/application_job.rb | 4 - app/jobs/client_upload_job.rb | 30 - app/jobs/mail_sort_job.rb | 77 - app/jobs/postal_worker_job.rb | 37 - app/mailers/api_mailer.rb | 30 - app/mailers/application_mailer.rb | 10 - app/models/application_record.rb | 12 - app/models/callback.rb | 18 - app/models/client.rb | 24 - app/models/client_environment.rb | 38 - app/models/client_upload.rb | 38 - app/models/concerns/.keep | 0 app/models/mailing_topic.rb | 11 - app/models/message.rb | 53 - app/models/message_activity.rb | 11 - app/models/message_activity_recipient.rb | 6 - app/models/message_recipient.rb | 16 - app/models/subscriber.rb | 13 - app/models/subscription.rb | 15 - app/models/template.rb | 15 - app/models/user.rb | 26 - app/views/active_storage/blobs/_blob.html.erb | 14 - .../api_mailer/reroute_message.html.haml | 34 - app/views/api_mailer/reroute_message.text.erb | 16 - app/views/api_mailer/send_message.html.haml | 1 - app/views/api_mailer/send_message.text.haml | 1 - app/views/client_environments/_form.html.haml | 13 - app/views/client_environments/edit.html.haml | 13 - app/views/client_environments/new.html.haml | 13 - app/views/client_uploads/new.html.haml | 28 - app/views/clients/_environments.html.haml | 37 - app/views/clients/_form.html.haml | 29 - app/views/clients/_header.html.haml | 19 - app/views/clients/_overview.html.haml | 28 - app/views/clients/_templates.html.haml | 30 - app/views/clients/_topics.html.haml | 32 - app/views/clients/_uploads.html.haml | 29 - app/views/clients/edit.html.haml | 14 - app/views/clients/index.html.haml | 32 - app/views/clients/messages.html.haml | 43 - app/views/clients/new.html.haml | 13 - app/views/clients/new_email.html.haml | 52 - app/views/clients/show.html.haml | 27 - app/views/devise/confirmations/new.html.haml | 18 - .../confirmation_instructions.html.haml | 4 - .../devise/mailer/password_change.html.erb | 3 - .../reset_password_instructions.html.erb | 8 - .../mailer/unlock_instructions.html.erb | 7 - app/views/devise/passwords/edit.html.haml | 18 - app/views/devise/passwords/new.html.haml | 13 - app/views/devise/registrations/edit.html.haml | 27 - app/views/devise/registrations/new.html.haml | 28 - app/views/devise/sessions/new.html.haml | 30 - .../devise/shared/_error_messages.html.haml | 6 - app/views/devise/shared/_links.html.haml | 24 - app/views/devise/unlocks/new.html.haml | 11 - app/views/home/index.html.haml | 13 - app/views/kaminari/_first_page.html.haml | 3 - app/views/kaminari/_gap.html.haml | 2 - app/views/kaminari/_last_page.html.haml | 3 - app/views/kaminari/_next_page.html.haml | 3 - app/views/kaminari/_page.html.haml | 8 - app/views/kaminari/_paginator.html.haml | 12 - app/views/kaminari/_prev_page.html.haml | 3 - app/views/layouts/application.html.haml | 19 - app/views/layouts/devise.html.haml | 24 - app/views/layouts/mailer.html.haml | 6 - app/views/layouts/mailer.text.haml | 1 - app/views/layouts/partials/_alerts.html.haml | 10 - app/views/layouts/partials/_footer.html.haml | 8 - app/views/layouts/partials/_header.html.haml | 14 - app/views/layouts/partials/_logout.html.haml | 16 - app/views/layouts/partials/_navbar.html.haml | 11 - app/views/layouts/partials/_sidebar.html.haml | 33 - app/views/mailing_topics/_form.html.haml | 16 - app/views/mailing_topics/edit.html.haml | 13 - app/views/mailing_topics/new.html.haml | 13 - app/views/messages/_activity.html.haml | 23 - app/views/messages/_header.html.haml | 22 - app/views/messages/_overview.html.haml | 31 - app/views/messages/index.html.haml | 27 - app/views/messages/links.haml | 19 - app/views/messages/logs.haml | 27 - app/views/messages/preview.html.haml | 1 - app/views/messages/recipients.html.haml | 30 - app/views/messages/show.html.haml | 4 - app/views/subscribers/_form.html.haml | 9 - app/views/subscribers/edit.html.haml | 13 - app/views/subscribers/index.html.haml | 39 - app/views/subscribers/new.html.haml | 14 - app/views/subscribers/show.html.haml | 29 - app/views/subscriptions/_form.html.haml | 11 - app/views/subscriptions/edit.html.haml | 14 - app/views/subscriptions/index.html.haml | 26 - app/views/templates/_form.html.haml | 30 - app/views/templates/edit.html.haml | 13 - app/views/templates/new.html.haml | 13 - app/views/templates/show.html.haml | 17 - babel.config.js | 70 - bin/bundle | 3 - bin/rails | 4 - bin/rake | 4 - bin/setup | 36 - bin/spring | 17 - bin/update | 31 - bin/webpack | 18 - bin/webpack-dev-server | 18 - bin/yarn | 11 - config.ru | 7 - config/application.rb | 45 - config/boot.rb | 6 - config/cable.yml | 10 - config/credentials.yml.enc | 1 - config/database.yml | 30 - config/deploy/prod.nomad | 171 - config/environment.rb | 7 - config/environments/development.rb | 49 - config/environments/production.rb | 53 - config/environments/review.rb | 7 - config/environments/staging.rb | 3 - config/environments/test.rb | 34 - .../application_controller_renderer.rb | 10 - config/initializers/assets.rb | 16 - config/initializers/backtrace_silencers.rb | 9 - config/initializers/bootstrap_html_errors.rb | 26 - .../initializers/content_security_policy.rb | 31 - config/initializers/cookies_serializer.rb | 7 - config/initializers/devise.rb | 290 - .../initializers/filter_parameter_logging.rb | 6 - config/initializers/hermes.rb | 3 - config/initializers/inflections.rb | 18 - config/initializers/kaminari.rb | 12 - config/initializers/lograge.rb | 19 - config/initializers/mime_types.rb | 6 - .../new_framework_defaults_6_0.rb | 47 - config/initializers/pinglish.rb | 29 - config/initializers/sentry.rb | 9 - config/initializers/sidekiq.rb | 27 - config/initializers/wrap_parameters.rb | 16 - config/locales/devise.en.yml | 64 - config/locales/en.yml | 128 - config/puma.rb | 40 - config/routes.rb | 38 - config/spring.rb | 8 - config/storage.yml | 15 - config/webpack/development.js | 5 - config/webpack/environment.js | 3 - config/webpack/production.js | 5 - config/webpack/test.js | 5 - config/webpacker.yml | 84 - db/migrate/20181129033057_create_clients.rb | 16 - .../20181130001936_devise_create_users.rb | 30 - db/migrate/20181130025912_create_mail_logs.rb | 16 - ...ename_type_to_content_type_on_mail_logs.rb | 5 - .../20181203045905_add_environment_to_api.rb | 5 - .../20181203192943_create_read_receipts.rb | 22 - .../20190721042119_create_message_activity.rb | 57 - ...200901160838_create_client_environments.rb | 20 - .../20200901221528_add_remaining_fields.rb | 7 - db/migrate/20200906074526_create_templates.rb | 15 - .../20200906074539_create_mailing_topics.rb | 26 - .../20200915033340_missing_foreign_keys.rb | 10 - ...1422_remove_client_environment_defaults.rb | 6 - .../20200915200614_improve_subscriptions.rb | 11 - .../20200915201651_add_missing_indexes.rb | 11 - ...te_active_storage_tables.active_storage.rb | 27 - .../20200918063434_create_client_uploads.rb | 10 - ...0_create_action_text_tables.action_text.rb | 14 - ..._attachments_for_blob_id.active_storage.rb | 10 - ...0210813191801_add_regex_to_environments.rb | 5 - db/schema.rb | 245 - db/seeds.rb | 16 - docker-compose.yml | 59 - lib/aws_notification.rb | 38 - lib/bulk_upload/subscriber_importer.rb | 58 - lib/hermes_app.rb | 46 - lib/mail_merge.rb | 45 - lib/mailchimp/api_client.rb | 14 - lib/message_factory.rb | 22 - lib/message_recipient_factory.rb | 9 - .../base_notification_handler.rb | 15 - lib/notification_handlers/bounce_handler.rb | 59 - lib/notification_handlers/click_handler.rb | 33 - .../complaint_handler.rb | 56 - .../delivered_handler.rb | 42 - lib/notification_handlers/ignored_handler.rb | 11 - lib/notification_handlers/opened_handler.rb | 27 - lib/notification_handlers/reject_handler.rb | 18 - lib/notification_handlers/send_handler.rb | 17 - .../subscribe_handler.rb | 15 - lib/notification_processor.rb | 42 - lib/plain_text.rb | 35 - lib/redis_config_builder.rb | 23 - lib/sidebar_helpers.rb | 39 - lib/tasks/db_exists.rake | 15 - package.json | 25 - postcss.config.js | 12 - public/404.html | 67 - public/422.html | 67 - public/500.html | 66 - public/apple-touch-icon-precomposed.png | 0 public/apple-touch-icon.png | 0 public/favicon.ico | 0 public/img/masks/avatar-group-hover-last.svg | 9 - public/img/masks/avatar-group-hover.svg | 10 - public/img/masks/avatar-group.svg | 9 - public/img/masks/avatar-status.svg | 9 - public/img/masks/icon-status.svg | 9 - public/logo.png | Bin 696 -> 0 bytes public/robots.txt | 2 - scripts/app | 20 - scripts/bootstrap | 15 - scripts/cibuild | 20 - scripts/console | 0 scripts/server | 0 scripts/setup | 0 scripts/test | 39 - scripts/update | 0 scripts/webpack | 7 - scripts/worker | 28 - spec/factories/clients.rb | 21 - spec/factories/messages.rb | 11 - spec/factories/users.rb | 9 - spec/fixtures/notifications/click.json | 12 - spec/fixtures/notifications/delivery.json | 12 - spec/fixtures/notifications/open.json | 12 - spec/fixtures/notifications/send.json | 12 - spec/initializers/shoulda_matchers.rb | 8 - spec/lib/aws_notification_spec.rb | 22 - spec/lib/notification_processor_spec.rb | 22 - spec/mailers/api_mailer_spec.rb | 6 - spec/mailers/previews/api_mailer_preview.rb | 8 - spec/models/client_spec.rb | 21 - spec/models/message_spec.rb | 27 - spec/models/user_spec.rb | 24 - spec/rails_helper.rb | 22 - spec/requests/api_messages_spec.rb | 100 - spec/spec_helper.rb | 21 - spec/support/factory_bot.rb | 5 - spec/support/helper_methods.rb | 32 - vendor/hermes-gem | 1 - yarn.lock | 7074 ----------------- 293 files changed, 15043 deletions(-) create mode 100644 .DS_Store delete mode 100644 .browserslistrc delete mode 100644 .dockerignore delete mode 100644 .github/CODEOWNERS delete mode 100644 .github/PULL_REQUEST_TEMPLATE/default.md delete mode 100644 .github/workflows/ci.yaml delete mode 100644 .github/workflows/docker.yaml delete mode 100644 .gitignore delete mode 100644 .rubocop.yml delete mode 100644 .ruby-version delete mode 100644 BRANCH delete mode 100644 CHANGELOG.md delete mode 100644 COMMIT delete mode 100644 Dockerfile delete mode 100644 Gemfile delete mode 100644 Gemfile.lock delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 Rakefile delete mode 100644 VERSION delete mode 100644 app/assets/config/manifest.js delete mode 100644 app/assets/images/.keep delete mode 100644 app/assets/images/logo.png delete mode 100644 app/assets/stylesheets/actiontext.scss delete mode 100644 app/assets/stylesheets/application.scss delete mode 100644 app/components/sidebar_component.rb delete mode 100644 app/components/sidebar_component/sidebar_component.html.haml delete mode 100644 app/controllers/api/messages_controller.rb delete mode 100644 app/controllers/api/notifications_controller.rb delete mode 100644 app/controllers/application_controller.rb delete mode 100644 app/controllers/client_environments_controller.rb delete mode 100644 app/controllers/client_uploads_controller.rb delete mode 100644 app/controllers/clients_controller.rb delete mode 100644 app/controllers/concerns/.keep delete mode 100644 app/controllers/home_controller.rb delete mode 100644 app/controllers/mailing_topics_controller.rb delete mode 100644 app/controllers/messages_controller.rb delete mode 100644 app/controllers/subscribers_controller.rb delete mode 100644 app/controllers/subscriptions_controller.rb delete mode 100644 app/controllers/templates_controller.rb delete mode 100644 app/controllers/turbo_controller.rb delete mode 100644 app/forms/adhoc_email_form.rb delete mode 100644 app/forms/application_form.rb delete mode 100644 app/helpers/application_helper.rb delete mode 100644 app/helpers/client_uploads_helper.rb delete mode 100644 app/helpers/messages_helper.rb delete mode 100644 app/helpers/subscriptions_helper.rb delete mode 100644 app/javascript/application.js delete mode 100644 app/javascript/controllers/sidebar_controller.js delete mode 100644 app/javascript/importmap.json.erb delete mode 100644 app/javascript/packs/main.js delete mode 100644 app/jobs/application_job.rb delete mode 100644 app/jobs/client_upload_job.rb delete mode 100644 app/jobs/mail_sort_job.rb delete mode 100644 app/jobs/postal_worker_job.rb delete mode 100644 app/mailers/api_mailer.rb delete mode 100644 app/mailers/application_mailer.rb delete mode 100644 app/models/application_record.rb delete mode 100644 app/models/callback.rb delete mode 100644 app/models/client.rb delete mode 100644 app/models/client_environment.rb delete mode 100644 app/models/client_upload.rb delete mode 100644 app/models/concerns/.keep delete mode 100644 app/models/mailing_topic.rb delete mode 100644 app/models/message.rb delete mode 100644 app/models/message_activity.rb delete mode 100644 app/models/message_activity_recipient.rb delete mode 100644 app/models/message_recipient.rb delete mode 100644 app/models/subscriber.rb delete mode 100644 app/models/subscription.rb delete mode 100644 app/models/template.rb delete mode 100644 app/models/user.rb delete mode 100644 app/views/active_storage/blobs/_blob.html.erb delete mode 100644 app/views/api_mailer/reroute_message.html.haml delete mode 100644 app/views/api_mailer/reroute_message.text.erb delete mode 100644 app/views/api_mailer/send_message.html.haml delete mode 100644 app/views/api_mailer/send_message.text.haml delete mode 100644 app/views/client_environments/_form.html.haml delete mode 100644 app/views/client_environments/edit.html.haml delete mode 100644 app/views/client_environments/new.html.haml delete mode 100644 app/views/client_uploads/new.html.haml delete mode 100644 app/views/clients/_environments.html.haml delete mode 100644 app/views/clients/_form.html.haml delete mode 100644 app/views/clients/_header.html.haml delete mode 100644 app/views/clients/_overview.html.haml delete mode 100644 app/views/clients/_templates.html.haml delete mode 100644 app/views/clients/_topics.html.haml delete mode 100644 app/views/clients/_uploads.html.haml delete mode 100644 app/views/clients/edit.html.haml delete mode 100644 app/views/clients/index.html.haml delete mode 100644 app/views/clients/messages.html.haml delete mode 100644 app/views/clients/new.html.haml delete mode 100644 app/views/clients/new_email.html.haml delete mode 100644 app/views/clients/show.html.haml delete mode 100644 app/views/devise/confirmations/new.html.haml delete mode 100644 app/views/devise/mailer/confirmation_instructions.html.haml delete mode 100644 app/views/devise/mailer/password_change.html.erb delete mode 100644 app/views/devise/mailer/reset_password_instructions.html.erb delete mode 100644 app/views/devise/mailer/unlock_instructions.html.erb delete mode 100644 app/views/devise/passwords/edit.html.haml delete mode 100644 app/views/devise/passwords/new.html.haml delete mode 100644 app/views/devise/registrations/edit.html.haml delete mode 100644 app/views/devise/registrations/new.html.haml delete mode 100644 app/views/devise/sessions/new.html.haml delete mode 100644 app/views/devise/shared/_error_messages.html.haml delete mode 100644 app/views/devise/shared/_links.html.haml delete mode 100644 app/views/devise/unlocks/new.html.haml delete mode 100644 app/views/home/index.html.haml delete mode 100644 app/views/kaminari/_first_page.html.haml delete mode 100644 app/views/kaminari/_gap.html.haml delete mode 100644 app/views/kaminari/_last_page.html.haml delete mode 100644 app/views/kaminari/_next_page.html.haml delete mode 100644 app/views/kaminari/_page.html.haml delete mode 100644 app/views/kaminari/_paginator.html.haml delete mode 100644 app/views/kaminari/_prev_page.html.haml delete mode 100644 app/views/layouts/application.html.haml delete mode 100644 app/views/layouts/devise.html.haml delete mode 100644 app/views/layouts/mailer.html.haml delete mode 100644 app/views/layouts/mailer.text.haml delete mode 100644 app/views/layouts/partials/_alerts.html.haml delete mode 100644 app/views/layouts/partials/_footer.html.haml delete mode 100644 app/views/layouts/partials/_header.html.haml delete mode 100644 app/views/layouts/partials/_logout.html.haml delete mode 100644 app/views/layouts/partials/_navbar.html.haml delete mode 100644 app/views/layouts/partials/_sidebar.html.haml delete mode 100644 app/views/mailing_topics/_form.html.haml delete mode 100644 app/views/mailing_topics/edit.html.haml delete mode 100644 app/views/mailing_topics/new.html.haml delete mode 100644 app/views/messages/_activity.html.haml delete mode 100644 app/views/messages/_header.html.haml delete mode 100644 app/views/messages/_overview.html.haml delete mode 100644 app/views/messages/index.html.haml delete mode 100644 app/views/messages/links.haml delete mode 100644 app/views/messages/logs.haml delete mode 100644 app/views/messages/preview.html.haml delete mode 100644 app/views/messages/recipients.html.haml delete mode 100644 app/views/messages/show.html.haml delete mode 100644 app/views/subscribers/_form.html.haml delete mode 100644 app/views/subscribers/edit.html.haml delete mode 100644 app/views/subscribers/index.html.haml delete mode 100644 app/views/subscribers/new.html.haml delete mode 100644 app/views/subscribers/show.html.haml delete mode 100644 app/views/subscriptions/_form.html.haml delete mode 100644 app/views/subscriptions/edit.html.haml delete mode 100644 app/views/subscriptions/index.html.haml delete mode 100644 app/views/templates/_form.html.haml delete mode 100644 app/views/templates/edit.html.haml delete mode 100644 app/views/templates/new.html.haml delete mode 100644 app/views/templates/show.html.haml delete mode 100644 babel.config.js delete mode 100755 bin/bundle delete mode 100755 bin/rails delete mode 100755 bin/rake delete mode 100755 bin/setup delete mode 100755 bin/spring delete mode 100755 bin/update delete mode 100755 bin/webpack delete mode 100755 bin/webpack-dev-server delete mode 100755 bin/yarn delete mode 100644 config.ru delete mode 100644 config/application.rb delete mode 100644 config/boot.rb delete mode 100644 config/cable.yml delete mode 100644 config/credentials.yml.enc delete mode 100644 config/database.yml delete mode 100644 config/deploy/prod.nomad delete mode 100644 config/environment.rb delete mode 100644 config/environments/development.rb delete mode 100644 config/environments/production.rb delete mode 100644 config/environments/review.rb delete mode 100644 config/environments/staging.rb delete mode 100644 config/environments/test.rb delete mode 100644 config/initializers/application_controller_renderer.rb delete mode 100644 config/initializers/assets.rb delete mode 100644 config/initializers/backtrace_silencers.rb delete mode 100644 config/initializers/bootstrap_html_errors.rb delete mode 100644 config/initializers/content_security_policy.rb delete mode 100644 config/initializers/cookies_serializer.rb delete mode 100644 config/initializers/devise.rb delete mode 100644 config/initializers/filter_parameter_logging.rb delete mode 100644 config/initializers/hermes.rb delete mode 100644 config/initializers/inflections.rb delete mode 100644 config/initializers/kaminari.rb delete mode 100644 config/initializers/lograge.rb delete mode 100644 config/initializers/mime_types.rb delete mode 100644 config/initializers/new_framework_defaults_6_0.rb delete mode 100644 config/initializers/pinglish.rb delete mode 100644 config/initializers/sentry.rb delete mode 100644 config/initializers/sidekiq.rb delete mode 100644 config/initializers/wrap_parameters.rb delete mode 100644 config/locales/devise.en.yml delete mode 100644 config/locales/en.yml delete mode 100644 config/puma.rb delete mode 100644 config/routes.rb delete mode 100644 config/spring.rb delete mode 100644 config/storage.yml delete mode 100644 config/webpack/development.js delete mode 100644 config/webpack/environment.js delete mode 100644 config/webpack/production.js delete mode 100644 config/webpack/test.js delete mode 100644 config/webpacker.yml delete mode 100644 db/migrate/20181129033057_create_clients.rb delete mode 100644 db/migrate/20181130001936_devise_create_users.rb delete mode 100644 db/migrate/20181130025912_create_mail_logs.rb delete mode 100644 db/migrate/20181201025601_rename_type_to_content_type_on_mail_logs.rb delete mode 100644 db/migrate/20181203045905_add_environment_to_api.rb delete mode 100644 db/migrate/20181203192943_create_read_receipts.rb delete mode 100644 db/migrate/20190721042119_create_message_activity.rb delete mode 100644 db/migrate/20200901160838_create_client_environments.rb delete mode 100644 db/migrate/20200901221528_add_remaining_fields.rb delete mode 100644 db/migrate/20200906074526_create_templates.rb delete mode 100644 db/migrate/20200906074539_create_mailing_topics.rb delete mode 100644 db/migrate/20200915033340_missing_foreign_keys.rb delete mode 100644 db/migrate/20200915051422_remove_client_environment_defaults.rb delete mode 100644 db/migrate/20200915200614_improve_subscriptions.rb delete mode 100644 db/migrate/20200915201651_add_missing_indexes.rb delete mode 100644 db/migrate/20200915202953_create_active_storage_tables.active_storage.rb delete mode 100644 db/migrate/20200918063434_create_client_uploads.rb delete mode 100644 db/migrate/20210328002100_create_action_text_tables.action_text.rb delete mode 100644 db/migrate/20210328005405_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb delete mode 100644 db/migrate/20210813191801_add_regex_to_environments.rb delete mode 100644 db/schema.rb delete mode 100644 db/seeds.rb delete mode 100644 docker-compose.yml delete mode 100644 lib/aws_notification.rb delete mode 100644 lib/bulk_upload/subscriber_importer.rb delete mode 100644 lib/hermes_app.rb delete mode 100644 lib/mail_merge.rb delete mode 100644 lib/mailchimp/api_client.rb delete mode 100644 lib/message_factory.rb delete mode 100644 lib/message_recipient_factory.rb delete mode 100644 lib/notification_handlers/base_notification_handler.rb delete mode 100644 lib/notification_handlers/bounce_handler.rb delete mode 100644 lib/notification_handlers/click_handler.rb delete mode 100644 lib/notification_handlers/complaint_handler.rb delete mode 100644 lib/notification_handlers/delivered_handler.rb delete mode 100644 lib/notification_handlers/ignored_handler.rb delete mode 100644 lib/notification_handlers/opened_handler.rb delete mode 100644 lib/notification_handlers/reject_handler.rb delete mode 100644 lib/notification_handlers/send_handler.rb delete mode 100644 lib/notification_handlers/subscribe_handler.rb delete mode 100644 lib/notification_processor.rb delete mode 100644 lib/plain_text.rb delete mode 100644 lib/redis_config_builder.rb delete mode 100644 lib/sidebar_helpers.rb delete mode 100644 lib/tasks/db_exists.rake delete mode 100644 package.json delete mode 100644 postcss.config.js delete mode 100644 public/404.html delete mode 100644 public/422.html delete mode 100644 public/500.html delete mode 100644 public/apple-touch-icon-precomposed.png delete mode 100644 public/apple-touch-icon.png delete mode 100644 public/favicon.ico delete mode 100644 public/img/masks/avatar-group-hover-last.svg delete mode 100644 public/img/masks/avatar-group-hover.svg delete mode 100644 public/img/masks/avatar-group.svg delete mode 100644 public/img/masks/avatar-status.svg delete mode 100644 public/img/masks/icon-status.svg delete mode 100644 public/logo.png delete mode 100644 public/robots.txt delete mode 100755 scripts/app delete mode 100644 scripts/bootstrap delete mode 100755 scripts/cibuild delete mode 100644 scripts/console delete mode 100644 scripts/server delete mode 100644 scripts/setup delete mode 100755 scripts/test delete mode 100644 scripts/update delete mode 100755 scripts/webpack delete mode 100755 scripts/worker delete mode 100644 spec/factories/clients.rb delete mode 100644 spec/factories/messages.rb delete mode 100644 spec/factories/users.rb delete mode 100644 spec/fixtures/notifications/click.json delete mode 100644 spec/fixtures/notifications/delivery.json delete mode 100644 spec/fixtures/notifications/open.json delete mode 100644 spec/fixtures/notifications/send.json delete mode 100644 spec/initializers/shoulda_matchers.rb delete mode 100644 spec/lib/aws_notification_spec.rb delete mode 100644 spec/lib/notification_processor_spec.rb delete mode 100644 spec/mailers/api_mailer_spec.rb delete mode 100644 spec/mailers/previews/api_mailer_preview.rb delete mode 100644 spec/models/client_spec.rb delete mode 100644 spec/models/message_spec.rb delete mode 100644 spec/models/user_spec.rb delete mode 100644 spec/rails_helper.rb delete mode 100644 spec/requests/api_messages_spec.rb delete mode 100644 spec/spec_helper.rb delete mode 100644 spec/support/factory_bot.rb delete mode 100644 spec/support/helper_methods.rb delete mode 160000 vendor/hermes-gem delete mode 100644 yarn.lock diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..38075d0b94068c7a36b6b99f8935c7cb37fdebe2 GIT binary patch literal 8196 zcmeHMTWl0n7(U;$(Ag=MQz+1>EG|}&(gH0|pn$k^i!HYl*+MT|*4>?fPMFS=o!Ko& zh*i)hG@5ACM2SXy6mQW7qDB)Rh#DRYF`|hNVtmmDAB+$Bfd82@3$%rV_+T*1N#^`> z{{MV4=X~e;XZFl8#?VnTS{bWjjHz@8%d4rnK@o9rOe#v~sU!=+Gd9GEESDSgMsoI~ z-jO3>AYve5AYve5AY$NlV1VA)qNq1{@5^XZM+`&^+>s23=R<-HVUwX9lQwvCP!((e z$cimMQ0ScY0Rbiv+GJ?Qqz#~SO}TqO2t~NXfP_;#A-a=IhIUL^31^UShVae^cPI$% zPPjzSogpc0R7VU%3`}M~q)!!F#tt!y`Pc8?-5f>EZ<+e zA$K(GXZ@nrkuB^MtzOr)bLI1FZjWV-W_WGNb^NU5n1ujf876hv*Jn9~JKEtE9m5N- zX&H!7$?*E)$5*tswKXT&TiZ`GCyuwawybSVtZrL#;zUfH)3AK~uFPS3*l|zGsUUnD zu;~+~_Vna=*dW)`E}WMd)2j8p{sAq+XO(F1JtMy5I^G_$;E~PnnI27Y zOWt*M7EBTE%e!`Q*zq#FCZDzQMLX-8n`}F6J!*RWzIoIaXM>(w@KZs@ev7cem*KqV znY&B^SS7QQU|#Knp(A#7+MM`3i<(;6);-v{Wyix8r_Y$lHEninU&->UoNW$dy}aod zmUC$LsAc#=gT$cYTL&$(5R28|?_MW6Y+jr@ua4{W`us9V_PvHxd4t+t%vnc@mVZp% zLr*M>sr8$+fMoB>4@U4{TIv^v(TwcX*iQ<4L#Pky2Iu#Q|~e?OD(7 z88Mx!qw4CW*!e+kC|fXlMoDQQrfa*Z2CGJX0orU>zFUx#B=nuCIv_5$$uQ_jd|ut$ zU1?pXrLmlnMY^UXm-6P{sH)nKTq0K}ptT{{B3m(fW9gJRN!HEwF_Vq3W9&40m7QU4 zvya%P>^!@`F0t>~59~*Fnf=E8V1J>V#YrIXqdo(GgS^gU1HjdJ8hc@uxAtNZrI zn@iI~rqs-uT{~w%!{VhYR9S19FVb6LDa;}w)pu>iX= z-lTD;vav>M*LWqRmTYd&Hfo%SY?tj#@l>3PMEMtjeUF`EpOIiMl3;&fzp~%i6%y$T z)R90JVKExfjHM*fwP?qBY`|u8p&MICvc1@YJ`7+Gd6*>FAy_EDM-e4FhQ~>^r|=|+ z_E|iK=kWs0;5EFCH}Ga4-w*Kd1UYUUFGqYbS&pT2!LeQE5Jk!&9uJCIx5z++>{loD z|C?|A{r?uP7Iljlh#2@kGJwj?bY};R{ASNng<=Uh9-%`N(Qi!J078}MBK*O2ob1&< l4Cy=(#*(2Ola?Y>{__t3!7uvg{eS%r*695oNb!!U{sFtFD@y- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 - redis: - image: redis - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 6379:6379 - steps: - - name: checkout - uses: actions/checkout@v2 - - - name: Configure ruby - uses: ruby/setup-ruby@v1 - env: - BUNDLE_RUBYGEMS__PKG__GITHUB__COM: ${{ github.actor }}:${{ secrets.PACKAGE_TOKEN }} - with: - bundler-cache: true - - # - name: precompile assets - # run: | - # ELASTIC_APM_ENABLED=false ASSETS_PRECOMPILE=1 SECRET_KEY_BASE=1 \ - # RAILS_ENV=test bundle exec rake assets:precompile - - - name: setup database - run: ./bin/rails db:setup - - - name: rspec - run: ./scripts/cibuild rspec diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml deleted file mode 100644 index ab5b388..0000000 --- a/.github/workflows/docker.yaml +++ /dev/null @@ -1,74 +0,0 @@ -name: docker - -on: - push: - branches: - - main - pull_request: - branches: - - main - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -jobs: - build: - name: build - runs-on: ubuntu-latest - steps: - - name: checkout - uses: actions/checkout@v2 - - - name: setup docker buildx - uses: docker/setup-buildx-action@v1 - - - name: setup cache - uses: actions/cache@v2 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-buildx- - - - name: registry login - uses: docker/login-action@v1 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.PACKAGE_TOKEN }} - - - name: register docker meta - id: meta - uses: docker/metadata-action@v3 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=branch - type=ref,event=pr - type=ref,event=tag - type=raw,enable=${{ github.ref == 'refs/heads/master' }},value=latest - - - name: write build info - run: | - echo $GITHUB_REF > BRANCH - echo $GITHUB_ACTOR > AUTHOR - echo $GITHUB_SHA > COMMIT - - - name: build image and export - uses: docker/build-push-action@v2 - with: - context: . - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache-new - - # Temp fix - # https://github.com/docker/build-push-action/issues/252 - # https://github.com/moby/buildkit/issues/1896 - - name: move cache - run: | - rm -rf /tmp/.buildx-cache - mv /tmp/.buildx-cache-new /tmp/.buildx-cache diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a0f213b..0000000 --- a/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# Gemfile.lock - -.bundle -.idea -.vscode -.byebug_history -.ds_store -/log -/tmp -/doc -/node_modules -/yarn-error.log -/storage -/public/assets - -!/log/.keep -!/tmp/.keep -/spec/examples.txt - -*.key -*.pdf - -/public/packs -/public/packs-test -/node_modules -/yarn-error.log -yarn-debug.log* -.yarn-integrity diff --git a/.rubocop.yml b/.rubocop.yml deleted file mode 100644 index 754f862..0000000 --- a/.rubocop.yml +++ /dev/null @@ -1,19 +0,0 @@ -AllCops: - NewCops: enable - Exclude: - - bin/**/* - - db/**/* - - node_modules/**/* - -Style/Documentation: - Enabled: No - -Layout/LineLength: - Max: 120 - -Metrics/MethodLength: - Max: 40 - -Metrics/BlockLength: - Exclude: - - spec/**/* diff --git a/.ruby-version b/.ruby-version deleted file mode 100644 index b502146..0000000 --- a/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -3.0.2 diff --git a/BRANCH b/BRANCH deleted file mode 100644 index c292d2a..0000000 --- a/BRANCH +++ /dev/null @@ -1 +0,0 @@ -local-development \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index b1fce22..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -# Changelog - -Please see [GitHub releases](https://github.com/mythcoders/hermes/releases). diff --git a/COMMIT b/COMMIT deleted file mode 100644 index 7b46ae3..0000000 --- a/COMMIT +++ /dev/null @@ -1 +0,0 @@ -0000000000 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 67d1d7c..0000000 --- a/Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -FROM ruby:3.0.2-alpine AS base - -ENV APP_HOME=/opt/hermes \ - GEM_HOME=/usr/local/bundle \ - BUNDLE_JOBS=4 \ - BUNDLE_RETRY=3 \ - LANG=en_US.UTF-8 \ - PATH=$GEM_HOME/bin:$GEM_HOME/gems/bin:$PATH \ - PATH=/root/.yarn/bin:$PATH - -RUN mkdir $APP_HOME -WORKDIR $APP_HOME -ADD Gemfile* $APP_HOME/ -COPY package.json yarn.lock $APP_HOME/ - -# Install packages -RUN apk update && \ - apk --no-cache add \ - alpine-sdk \ - build-base \ - coreutils \ - libcurl \ - nodejs \ - postgresql-dev \ - tzdata \ - less \ - git \ - vips - -# Set local timezone -RUN cp /usr/share/zoneinfo/US/Eastern /etc/localtime && \ - echo "US/Eastern" > /etc/timezone - -# Install yarn -RUN apk add --virtual build-yarn curl gnupg && \ - touch ~/.bashrc && \ - curl -o- -L https://yarnpkg.com/install.sh | sh -s -- --version 1.22.10 && \ - apk del build-yarn gnupg - -# Upgrade RubyGems and install required Bundler version -RUN gem update --system && gem install bundler -v 2.2.24 - -RUN bundle install -RUN yarn install --frozen-lockfile - -EXPOSE 5000 - -FROM base AS build - -ADD . $APP_HOME/ - -RUN ASSETS_PRECOMPILE=1 SECRET_KEY_BASE=1 NODE_ENV=production RAILS_ENV=production \ - bundle exec rake assets:precompile - -CMD ["sh", "./scripts/app", "start"] diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 80614de..0000000 --- a/Gemfile +++ /dev/null @@ -1,73 +0,0 @@ -# frozen_string_literal: true - -source "https://rubygems.org" -git_source(:github) { |repo| "https://github.com/#{repo}.git" } - -ruby "3.0.2" - -gem "aasm" -gem "aws-sdk-s3", require: false -gem "aws-sdk-sns", "~> 1" -gem "bootsnap", require: false -gem "devise" # security -gem "haml" -gem "hotwire-rails" -gem "jbuilder" # JSON APIs https://github.com/rails/jbuilder -gem "kaminari" # Pagination -gem "lograge" -gem "liquid" # template rendering -gem "paper_trail" -gem "pg" # database for Active Record -gem "pinglish" # app status checking -gem "puma" # app server -gem "rails", "~> 6.0.0" -gem "ransack" # Searching -gem "sass-rails" -gem "uglifier", ">= 1.3.0" -gem "view_component" -gem "webpacker" - -# sentry exceptions -gem "sentry-rails" -gem "sentry-ruby" -gem "sentry-sidekiq" - -# Sidekiq -gem "redis-namespace" -gem "sidekiq" -gem "sidekiq-scheduler" - -group :development, :test do - gem "better_errors" - gem "bundler-audit" - gem "byebug", platforms: %i[mri mingw x64_mingw] - gem "capybara" - gem "debase", "~> 0.2.5.beta2" - gem "factory_bot_rails" - gem "faker" - gem "guard-rspec" - gem "pry-byebug" - gem "pry-rails" - gem "rails-controller-testing" - gem "rspec_junit_formatter" - gem "rspec-rails" - gem "ruby-debug-ide" - gem "shoulda-matchers" - gem "simplecov", require: false - gem "standard" -end - -group :development do - gem "listen", ">= 3.0.5", "< 3.2" - gem "spring" - gem "spring-watcher-listen", "~> 2.0.0" - gem "web-console", ">= 3.3.0" -end - -group :test do - gem "chromedriver-helper" - gem "selenium-webdriver" - gem "timecop" -end - -gem "tzinfo-data", platforms: %i[mingw mswin x64_mingw jruby] diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index ca320bd..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,514 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - aasm (5.2.0) - concurrent-ruby (~> 1.0) - actioncable (6.0.4.7) - actionpack (= 6.0.4.7) - nio4r (~> 2.0) - websocket-driver (>= 0.6.1) - actionmailbox (6.0.4.7) - actionpack (= 6.0.4.7) - activejob (= 6.0.4.7) - activerecord (= 6.0.4.7) - activestorage (= 6.0.4.7) - activesupport (= 6.0.4.7) - mail (>= 2.7.1) - actionmailer (6.0.4.7) - actionpack (= 6.0.4.7) - actionview (= 6.0.4.7) - activejob (= 6.0.4.7) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 2.0) - actionpack (6.0.4.7) - actionview (= 6.0.4.7) - activesupport (= 6.0.4.7) - rack (~> 2.0, >= 2.0.8) - rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.4.7) - actionpack (= 6.0.4.7) - activerecord (= 6.0.4.7) - activestorage (= 6.0.4.7) - activesupport (= 6.0.4.7) - nokogiri (>= 1.8.5) - actionview (6.0.4.7) - activesupport (= 6.0.4.7) - builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.4.7) - activesupport (= 6.0.4.7) - globalid (>= 0.3.6) - activemodel (6.0.4.7) - activesupport (= 6.0.4.7) - activerecord (6.0.4.7) - activemodel (= 6.0.4.7) - activesupport (= 6.0.4.7) - activestorage (6.0.4.7) - actionpack (= 6.0.4.7) - activejob (= 6.0.4.7) - activerecord (= 6.0.4.7) - marcel (~> 1.0.0) - activesupport (6.0.4.7) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) - addressable (2.8.0) - public_suffix (>= 2.0.2, < 5.0) - archive-zip (0.12.0) - io-like (~> 0.3.0) - ast (2.4.2) - aws-eventstream (1.1.1) - aws-partitions (1.487.0) - aws-sdk-core (3.119.0) - aws-eventstream (~> 1, >= 1.0.2) - aws-partitions (~> 1, >= 1.239.0) - aws-sigv4 (~> 1.1) - jmespath (~> 1.0) - aws-sdk-kms (1.46.0) - aws-sdk-core (~> 3, >= 3.119.0) - aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.98.0) - aws-sdk-core (~> 3, >= 3.119.0) - aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.1) - aws-sdk-sns (1.44.0) - aws-sdk-core (~> 3, >= 3.119.0) - aws-sigv4 (~> 1.1) - aws-sigv4 (1.2.4) - aws-eventstream (~> 1, >= 1.0.2) - bcrypt (3.1.16) - better_errors (2.9.1) - coderay (>= 1.0.0) - erubi (>= 1.0.0) - rack (>= 0.9.0) - bindex (0.8.1) - bootsnap (1.7.7) - msgpack (~> 1.0) - builder (3.2.4) - bundler-audit (0.8.0) - bundler (>= 1.2.0, < 3) - thor (~> 1.0) - byebug (11.1.3) - capybara (3.35.3) - addressable - mini_mime (>= 0.1.3) - nokogiri (~> 1.8) - rack (>= 1.6.0) - rack-test (>= 0.6.3) - regexp_parser (>= 1.5, < 3.0) - xpath (~> 3.2) - childprocess (3.0.0) - chromedriver-helper (2.1.1) - archive-zip (~> 0.10) - nokogiri (~> 1.8) - coderay (1.1.3) - concurrent-ruby (1.1.9) - connection_pool (2.2.5) - crass (1.0.6) - debase (0.2.5.beta2) - debase-ruby_core_source (>= 0.10.12) - debase-ruby_core_source (0.10.12) - devise (4.8.0) - bcrypt (~> 3.0) - orm_adapter (~> 0.1) - railties (>= 4.1.0) - responders - warden (~> 1.2.3) - diff-lcs (1.4.4) - docile (1.4.0) - e2mmap (0.1.0) - erubi (1.10.0) - et-orbi (1.2.4) - tzinfo - execjs (2.8.1) - factory_bot (6.2.0) - activesupport (>= 5.0.0) - factory_bot_rails (6.2.0) - factory_bot (~> 6.2.0) - railties (>= 5.0.0) - faker (2.18.0) - i18n (>= 1.6, < 2) - faraday (1.7.0) - faraday-em_http (~> 1.0) - faraday-em_synchrony (~> 1.0) - faraday-excon (~> 1.1) - faraday-httpclient (~> 1.0.1) - faraday-net_http (~> 1.0) - faraday-net_http_persistent (~> 1.1) - faraday-patron (~> 1.0) - faraday-rack (~> 1.0) - multipart-post (>= 1.2, < 3) - ruby2_keywords (>= 0.0.4) - faraday-em_http (1.0.0) - faraday-em_synchrony (1.0.0) - faraday-excon (1.1.0) - faraday-httpclient (1.0.1) - faraday-net_http (1.0.1) - faraday-net_http_persistent (1.2.0) - faraday-patron (1.0.0) - faraday-rack (1.0.0) - ffi (1.15.3) - formatador (0.3.0) - fugit (1.5.0) - et-orbi (~> 1.1, >= 1.1.8) - raabro (~> 1.4) - globalid (0.5.2) - activesupport (>= 5.0) - guard (2.18.0) - formatador (>= 0.2.4) - listen (>= 2.7, < 4.0) - lumberjack (>= 1.0.12, < 2.0) - nenv (~> 0.1) - notiffany (~> 0.0) - pry (>= 0.13.0) - shellany (~> 0.0) - thor (>= 0.18.1) - guard-compat (1.2.1) - guard-rspec (4.7.3) - guard (~> 2.1) - guard-compat (~> 1.1) - rspec (>= 2.99.0, < 4.0) - haml (5.2.2) - temple (>= 0.8.0) - tilt - hotwire-rails (0.1.3) - rails (>= 6.0.0) - stimulus-rails - turbo-rails - i18n (1.10.0) - concurrent-ruby (~> 1.0) - io-like (0.3.1) - jbuilder (2.11.2) - activesupport (>= 5.0.0) - jmespath (1.4.0) - kaminari (1.2.1) - activesupport (>= 4.1.0) - kaminari-actionview (= 1.2.1) - kaminari-activerecord (= 1.2.1) - kaminari-core (= 1.2.1) - kaminari-actionview (1.2.1) - actionview - kaminari-core (= 1.2.1) - kaminari-activerecord (1.2.1) - activerecord - kaminari-core (= 1.2.1) - kaminari-core (1.2.1) - liquid (5.0.1) - listen (3.0.8) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - lograge (0.11.2) - actionpack (>= 4) - activesupport (>= 4) - railties (>= 4) - request_store (~> 1.0) - loofah (2.12.0) - crass (~> 1.0.2) - nokogiri (>= 1.5.9) - lumberjack (1.2.8) - mail (2.7.1) - mini_mime (>= 0.1.1) - marcel (1.0.2) - method_source (1.0.0) - mini_mime (1.1.2) - minitest (5.15.0) - msgpack (1.4.2) - multipart-post (2.1.1) - nenv (0.3.0) - nio4r (2.5.8) - nokogiri (1.13.4-x86_64-darwin) - racc (~> 1.4) - nokogiri (1.13.4-x86_64-linux) - racc (~> 1.4) - notiffany (0.1.3) - nenv (~> 0.1) - shellany (~> 0.0) - orm_adapter (0.5.0) - paper_trail (12.0.0) - activerecord (>= 5.2) - request_store (~> 1.1) - parallel (1.20.1) - parser (3.0.2.0) - ast (~> 2.4.1) - pg (1.2.3) - pinglish (0.2.1) - rack - pry (0.13.1) - coderay (~> 1.1) - method_source (~> 1.0) - pry-byebug (3.9.0) - byebug (~> 11.0) - pry (~> 0.13.0) - pry-rails (0.3.9) - pry (>= 0.10.4) - public_suffix (4.0.6) - puma (5.6.4) - nio4r (~> 2.0) - raabro (1.4.0) - racc (1.6.0) - rack (2.2.3) - rack-proxy (0.7.0) - rack - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (6.0.4.7) - actioncable (= 6.0.4.7) - actionmailbox (= 6.0.4.7) - actionmailer (= 6.0.4.7) - actionpack (= 6.0.4.7) - actiontext (= 6.0.4.7) - actionview (= 6.0.4.7) - activejob (= 6.0.4.7) - activemodel (= 6.0.4.7) - activerecord (= 6.0.4.7) - activestorage (= 6.0.4.7) - activesupport (= 6.0.4.7) - bundler (>= 1.3.0) - railties (= 6.0.4.7) - sprockets-rails (>= 2.0.0) - rails-controller-testing (1.0.5) - actionpack (>= 5.0.1.rc1) - actionview (>= 5.0.1.rc1) - activesupport (>= 5.0.1.rc1) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) - nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) - loofah (~> 2.3) - railties (6.0.4.7) - actionpack (= 6.0.4.7) - activesupport (= 6.0.4.7) - method_source - rake (>= 0.8.7) - thor (>= 0.20.3, < 2.0) - rainbow (3.0.0) - rake (13.0.6) - ransack (2.4.2) - activerecord (>= 5.2.4) - activesupport (>= 5.2.4) - i18n - rb-fsevent (0.11.0) - rb-inotify (0.10.1) - ffi (~> 1.0) - redis (4.5.1) - redis-namespace (1.8.1) - redis (>= 3.0.4) - regexp_parser (2.1.1) - request_store (1.5.0) - rack (>= 1.4) - responders (3.0.1) - actionpack (>= 5.0) - railties (>= 5.0) - rexml (3.2.5) - rspec (3.10.0) - rspec-core (~> 3.10.0) - rspec-expectations (~> 3.10.0) - rspec-mocks (~> 3.10.0) - rspec-core (3.10.1) - rspec-support (~> 3.10.0) - rspec-expectations (3.10.1) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-mocks (3.10.2) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-rails (5.0.2) - actionpack (>= 5.2) - activesupport (>= 5.2) - railties (>= 5.2) - rspec-core (~> 3.10) - rspec-expectations (~> 3.10) - rspec-mocks (~> 3.10) - rspec-support (~> 3.10) - rspec-support (3.10.2) - rspec_junit_formatter (0.4.1) - rspec-core (>= 2, < 4, != 2.12.0) - rubocop (1.18.4) - parallel (~> 1.10) - parser (>= 3.0.0.0) - rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml - rubocop-ast (>= 1.8.0, < 2.0) - ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.10.0) - parser (>= 3.0.1.1) - rubocop-performance (1.11.4) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) - ruby-debug-ide (0.7.2) - rake (>= 0.8.1) - ruby-progressbar (1.11.0) - ruby2_keywords (0.0.5) - rubyzip (2.3.2) - rufus-scheduler (3.8.0) - fugit (~> 1.1, >= 1.1.6) - sass-rails (6.0.0) - sassc-rails (~> 2.1, >= 2.1.1) - sassc (2.4.0) - ffi (~> 1.9) - sassc-rails (2.1.2) - railties (>= 4.0.0) - sassc (>= 2.0) - sprockets (> 3.0) - sprockets-rails - tilt - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) - rubyzip (>= 1.2.2) - semantic_range (3.0.0) - sentry-rails (4.6.5) - railties (>= 5.0) - sentry-ruby-core (~> 4.6.0) - sentry-ruby (4.6.5) - concurrent-ruby (~> 1.0, >= 1.0.2) - faraday (>= 1.0) - sentry-ruby-core (= 4.6.5) - sentry-ruby-core (4.6.5) - concurrent-ruby - faraday - sentry-sidekiq (4.6.5) - sentry-ruby-core (~> 4.6.0) - sidekiq (>= 3.0) - shellany (0.0.1) - shoulda-matchers (5.0.0) - activesupport (>= 5.2.0) - sidekiq (6.4.0) - connection_pool (>= 2.2.2) - rack (~> 2.0) - redis (>= 4.2.0) - sidekiq-scheduler (3.1.0) - e2mmap - redis (>= 3, < 5) - rufus-scheduler (~> 3.2) - sidekiq (>= 3) - thwait - tilt (>= 1.4.0) - simplecov (0.21.2) - docile (~> 1.1) - simplecov-html (~> 0.11) - simplecov_json_formatter (~> 0.1) - simplecov-html (0.12.3) - simplecov_json_formatter (0.1.3) - spring (2.1.1) - spring-watcher-listen (2.0.1) - listen (>= 2.7, < 4.0) - spring (>= 1.2, < 3.0) - sprockets (4.0.3) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) - sprockets (>= 3.0.0) - standard (1.1.7) - rubocop (= 1.18.4) - rubocop-performance (= 1.11.4) - stimulus-rails (0.3.3) - rails (>= 6.0.0) - temple (0.8.2) - thor (1.1.0) - thread_safe (0.3.6) - thwait (0.2.0) - e2mmap - tilt (2.0.10) - timecop (0.9.4) - turbo-rails (0.7.2) - rails (>= 6.0.0) - tzinfo (1.2.9) - thread_safe (~> 0.1) - uglifier (4.2.0) - execjs (>= 0.3.0, < 3) - unicode-display_width (2.0.0) - view_component (2.49.1) - activesupport (>= 5.0.0, < 8.0) - method_source (~> 1.0) - warden (1.2.9) - rack (>= 2.0.9) - web-console (4.1.0) - actionview (>= 6.0.0) - activemodel (>= 6.0.0) - bindex (>= 0.4.0) - railties (>= 6.0.0) - webpacker (5.4.0) - activesupport (>= 5.2) - rack-proxy (>= 0.6.1) - railties (>= 5.2) - semantic_range (>= 2.3.0) - websocket-driver (0.7.5) - websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.5) - xpath (3.2.0) - nokogiri (~> 1.8) - zeitwerk (2.5.4) - -PLATFORMS - x86_64-darwin-21 - x86_64-linux-musl - -DEPENDENCIES - aasm - aws-sdk-s3 - aws-sdk-sns (~> 1) - better_errors - bootsnap - bundler-audit - byebug - capybara - chromedriver-helper - debase (~> 0.2.5.beta2) - devise - factory_bot_rails - faker - guard-rspec - haml - hotwire-rails - jbuilder - kaminari - liquid - listen (>= 3.0.5, < 3.2) - lograge - paper_trail - pg - pinglish - pry-byebug - pry-rails - puma - rails (~> 6.0.0) - rails-controller-testing - ransack - redis-namespace - rspec-rails - rspec_junit_formatter - ruby-debug-ide - sass-rails - selenium-webdriver - sentry-rails - sentry-ruby - sentry-sidekiq - shoulda-matchers - sidekiq - sidekiq-scheduler - simplecov - spring - spring-watcher-listen (~> 2.0.0) - standard - timecop - tzinfo-data - uglifier (>= 1.3.0) - view_component - web-console (>= 3.3.0) - webpacker - -RUBY VERSION - ruby 3.0.2p107 - -BUNDLED WITH - 2.2.24 diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 84a9e75..0000000 --- a/LICENSE +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 2019 Justin Adkins - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. diff --git a/README.md b/README.md deleted file mode 100644 index f3b58dc..0000000 --- a/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Hermes - -Application (and API) for logging emails and sending them to [Amazon Web Services Simple Email Service (SES)](https://aws.amazon.com/ses/) for delivery. - -MythCoders uses SES as a cost effective way to sent emails but the services unfortunately does not provide the ability to see a log of sent emails. Hermes fills that gap. - -## Features - -- Track email sending from multiple sources before sending to SES for delivery -- Use environments to apply rules when a client sends an email -- Easily see SMTP delivery results -- View when emails are opened and when links are clicked - -## Software - -Hermes is a Ruby on Rails application. The UI is built with [Halfmoon](https://www.gethalfmoon.com/) - -## Licensing - -See the [LICENSE](LICENSE) file for licensing information as it pertains to -files in this repository. diff --git a/Rakefile b/Rakefile deleted file mode 100644 index d2a78aa..0000000 --- a/Rakefile +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -# Add your own tasks in files placed in lib/tasks ending in .rake, -# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. - -require_relative "config/application" - -Rails.application.load_tasks diff --git a/VERSION b/VERSION deleted file mode 100644 index 5d4294b..0000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.5.1 \ No newline at end of file diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js deleted file mode 100644 index 5918193..0000000 --- a/app/assets/config/manifest.js +++ /dev/null @@ -1,2 +0,0 @@ -//= link_tree ../images -//= link_directory ../stylesheets .css diff --git a/app/assets/images/.keep b/app/assets/images/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/app/assets/images/logo.png b/app/assets/images/logo.png deleted file mode 100644 index d5cb3ec0761098e5f055cf5f4fa6346397e24308..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 696 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDB3?!H8JlO)ISkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq8r{zDi(Vu$sZZAYL$MSD+10LNUN6#1*8Vq2a)R13>Ek z|NjgPK!N`t0!V>~hM*L)P$11%666=m;PC858i^mS!_#3msw zXz=ik%?6-!yQhm|h{fsL%Nw%}8wju^{N`Pi(DXv>ChK}$lj;_!UE3Z6?YVaC!N!u4 z&!+Iq^j7eHknm@Ut*3hQs@e%p|9^VkqU=6Vc9Fe7d7#0^yIn3V%QJs@{F!q^=V43! zk=YMg^|h6@*ra4KKIUw3o7bJoYxLGr#cN^7)6%B(fhCJG+;{xzTl74+4S}TF3=0|jFK9%wBuWK6WB9s7#dFDy9|6<8#jJLD^km24*XlQ{ zf823eTw?#Uc~$p0oz6-I^Q9jm3bPXW1I)axZriwV!||uhLB1CX3W9wv>mJ-4bU2~m zj5J#Z4+EF^Wd)<0HB)mPoH(ycMDg>( znp=Wdd`}P9tdZI0|F5}j-_CQ4RmJ%`FC1ueS@v0gh2t5+T6TpQ!nbaRH>A&8V{}gS zS<5y)7d1wS!i2m-GqWEiv1xE8wE8<7|L%60CHP&-*&-3M^J_P>-r@|Y5ikG% diff --git a/app/assets/stylesheets/actiontext.scss b/app/assets/stylesheets/actiontext.scss deleted file mode 100644 index 7cb26e7..0000000 --- a/app/assets/stylesheets/actiontext.scss +++ /dev/null @@ -1,36 +0,0 @@ -// -// Provides a drop-in pointer for the default Trix stylesheet that will format the toolbar and -// the trix-editor content (whether displayed or under editing). Feel free to incorporate this -// inclusion directly in any other asset bundle and remove this file. -// -//= require trix/dist/trix - -// We need to override trix.css’s image gallery styles to accommodate the -// element we wrap around attachments. Otherwise, -// images in galleries will be squished by the max-width: 33%; rule. -.trix-content { - .attachment-gallery { - > action-text-attachment, - > .attachment { - flex: 1 0 33%; - padding: 0 0.5em; - max-width: 33%; - } - - &.attachment-gallery--2, - &.attachment-gallery--4 { - > action-text-attachment, - > .attachment { - flex-basis: 50%; - max-width: 50%; - } - } - } - - action-text-attachment { - .attachment { - padding: 0 !important; - max-width: 100% !important; - } - } -} diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss deleted file mode 100644 index 38a157a..0000000 --- a/app/assets/stylesheets/application.scss +++ /dev/null @@ -1,16 +0,0 @@ - -@import "halfmoon/css/halfmoon-variables"; -@import "actiontext"; - -.padded-body { - padding-top: 5rem; -} - -.action-column { - width: 10%; -} - -.px-card { - padding-left: var(--content-and-card-spacing-half); - padding-right: var(--content-and-card-spacing-half); -} \ No newline at end of file diff --git a/app/components/sidebar_component.rb b/app/components/sidebar_component.rb deleted file mode 100644 index 8b3ec9e..0000000 --- a/app/components/sidebar_component.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -class SidebarComponent < ViewComponent::Base - def initialize(user:, current_action:) - @user = user - @current_action = current_action - end -end diff --git a/app/components/sidebar_component/sidebar_component.html.haml b/app/components/sidebar_component/sidebar_component.html.haml deleted file mode 100644 index 3e21372..0000000 --- a/app/components/sidebar_component/sidebar_component.html.haml +++ /dev/null @@ -1 +0,0 @@ -%div Add Sidebar template here diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb deleted file mode 100644 index 0d170b2..0000000 --- a/app/controllers/api/messages_controller.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: true - -module Api - class MessagesController < ActionController::Base - skip_before_action :verify_authenticity_token - before_action :validate_api_credentials - before_action :validate_api_environment - - rescue_from ActionController::ParameterMissing do - head :bad_request - end - - def new - message = Message.build(mail_params, @client) - return render(json: message.errors, status: :bad_request) unless message.valid? - return head :error unless message.received! - - MailSortJob.perform_later message.tracking_id - head :created - end - - private - - def mail_params - params.require(:message).permit(:environment, :subject, :html_body, :text_body, :sender, to: [], cc: [], bcc: []) - end - - def validate_api_credentials - @client = authenticate_with_http_basic { |u, p| Client.authenticate(u, p) } - return head :unauthorized unless @client - - head :forbidden unless @client.is_active - end - - def validate_api_environment - return unless mail_params[:environment] - - head :method_not_allowed if client_environment.status == "rejected" - end - - def client_environment - @client_environment ||= ClientEnvironment.find_or_create_by_env!(@client.id, mail_params[:environment]) - end - end -end diff --git a/app/controllers/api/notifications_controller.rb b/app/controllers/api/notifications_controller.rb deleted file mode 100644 index efbf612..0000000 --- a/app/controllers/api/notifications_controller.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module Api - class NotificationsController < ActionController::Base - skip_before_action :verify_authenticity_token - before_action :verify_notification - - def new - NotificationProcessor.new(request_data).process - - head :ok - rescue => e - head :internal_server_error - raise e - end - - private - - def request_data - if request.content_type == "text/plain" - JSON.parse request.raw_post - else - params - end - end - - def verify_notification - return if Rails.env.development? - - return head :bad_request unless Aws::SNS::MessageVerifier.new.authentic?(request.raw_post) - end - end -end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb deleted file mode 100644 index 700ef07..0000000 --- a/app/controllers/application_controller.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -class ApplicationController < ActionController::Base - protect_from_forgery with: :exception - rescue_from ActiveRecord::RecordNotFound, with: :record_not_found - - before_action :configure_permitted_parameters, if: :devise_controller? - - private - - def configure_permitted_parameters - additional_fields = %i[name].freeze - devise_parameter_sanitizer.permit(:sign_up, keys: additional_fields) - devise_parameter_sanitizer.permit(:account_update, keys: additional_fields) - end -end diff --git a/app/controllers/client_environments_controller.rb b/app/controllers/client_environments_controller.rb deleted file mode 100644 index 1c77008..0000000 --- a/app/controllers/client_environments_controller.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -class ClientEnvironmentsController < ApplicationController - before_action :authenticate_user! - before_action :set_environment, only: %i[show edit update] - - def new - @environment = ClientEnvironment.new(client_id: params[:client_id]) - end - - def create - @environment = ClientEnvironment.new(environment_params) - if @environment.save - flash["success"] = t("created") - redirect_to client_path(@environment.client_id) - else - render "new" - end - end - - def update - if @environment.update(environment_params) - flash["success"] = t("updated") - redirect_to client_path(@environment.client_id) - else - render "edit", status: :unprocessable_entity - end - end - - private - - def set_environment - @environment = ClientEnvironment.find params[:id] - end - - def environment_params - params.require(:client_environment).permit(:client_id, :name, :status, :regex) - end -end diff --git a/app/controllers/client_uploads_controller.rb b/app/controllers/client_uploads_controller.rb deleted file mode 100644 index ce82e68..0000000 --- a/app/controllers/client_uploads_controller.rb +++ /dev/null @@ -1,54 +0,0 @@ -# frozen_string_literal: true - -class ClientUploadsController < ApplicationController - before_action :authenticate_user! - before_action :set_upload, only: %i[show edit update] - - def new - @upload = ClientUpload.new(client_id: params[:client_id]) - end - - def upload_subscribers - @client = Client.includes(:topics).find(params[:client_id]) - return unless params[:client_upload] - - @client.file_uploads.attach(upload_params) - flash[:success] = "something" - # Worker.perform_async 1 - # params[:client_upload][:file] - end - - def create - @upload = ClientUpload.new(upload_params) - @upload.data_file.attach(file_blob_param) - if @upload.save - flash["success"] = t("created") - redirect_to client_path(@upload.client_id) - else - render "new", status: :unprocessable_entity - end - end - - def update - if @upload.update(upload_params) - flash["success"] = t("updated") - redirect_to client_path(@upload.client_id) - else - render "edit", status: :unprocessable_entity - end - end - - private - - def set_upload - @upload = ClientUpload.find params[:id] - end - - def upload_params - params.require(:client_upload).permit(:client_id, :file_type) - end - - def file_blob_param - params[:client_upload][:file] - end -end diff --git a/app/controllers/clients_controller.rb b/app/controllers/clients_controller.rb deleted file mode 100644 index 0c5993f..0000000 --- a/app/controllers/clients_controller.rb +++ /dev/null @@ -1,69 +0,0 @@ -# frozen_string_literal: true - -class ClientsController < ApplicationController - before_action :authenticate_user! - before_action :set_client, only: %i[show edit update new_email messages] - - def index - @clients = Client.order(:name).page(params[:page]) - end - - def new - @client = Client.new(api_secret: SecureRandom.urlsafe_base64(64), api_key: SecureRandom.urlsafe_base64(64)) - end - - def create - @client = Client.new(client_params) - if @client.save - flash["success"] = t("created") - redirect_to client_path(@client) - else - render "new", status: :unprocessable_entity - end - end - - def update - if @client.update(client_params) - flash["success"] = t("updated") - redirect_to client_path(@client) - else - render "edit", status: :unprocessable_entity - end - end - - def new_email - @message = AdhocEmailForm.new - end - - def send_email - @message = AdhocEmailForm.new(email_params) - - if @message.save! - flash["success"] = t("updated") - redirect_to client_path(params[:client_id]) - else - flash["error"] = "Correct the errors" - render "new_email", status: :unprocessable_entity - end - end - - def messages - @messages = @client.messages.order(created_at: :desc).page(params[:page]) - end - - private - - def set_client - @client = Client.find(params[:id] || params[:client_id]) - end - - def client_params - params.require(:client).permit(:id, :name, :owner, :reroute_email, :reply_to_email, :api_secret, :api_key, - :is_active) - end - - def email_params - params.require(:adhoc_email_form).permit(:mailing_topic_id, :template_id, :environment_id, :subject, :html_body, - :text_body) - end -end diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb deleted file mode 100644 index 16758bc..0000000 --- a/app/controllers/home_controller.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -class HomeController < ApplicationController - before_action :authenticate_user! -end diff --git a/app/controllers/mailing_topics_controller.rb b/app/controllers/mailing_topics_controller.rb deleted file mode 100644 index 1966ef0..0000000 --- a/app/controllers/mailing_topics_controller.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -class MailingTopicsController < ApplicationController - before_action :authenticate_user! - before_action :set_topic, only: %i[show edit update] - - def new - @topic = MailingTopic.new(client_id: params[:client_id]) - end - - def create - @topic = MailingTopic.new(topic_params) - if @topic.save - flash["success"] = t("created") - redirect_to client_path(@topic.client_id) - else - render "new", status: :unprocessable_entity - end - end - - def update - if @topic.update(topic_params) - flash["success"] = t("updated") - redirect_to client_path(@topic.client_id) - else - render "edit", status: :unprocessable_entity - end - end - - private - - def set_topic - @topic = MailingTopic.find params[:id] - end - - def topic_params - params.require(:mailing_topic).permit(:client_id, :name, :description, :active) - end -end diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb deleted file mode 100644 index 15feec4..0000000 --- a/app/controllers/messages_controller.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true - -class MessagesController < ApplicationController - before_action :authenticate_user! - before_action :set_message, except: %i[index] - - def index - @messages = Message.order(created_at: :desc).page(params[:page]) - end - - def logs - @logs = @message.user_activity.order(created_at: :desc).page(params[:page]) - end - - def preview - render :preview, layout: false, cached: false - end - - def recipients - @recipients = @message.recipients.includes(:activities).order(created_at: :desc).page(params[:page]) - end - - private - - def set_message - @message = Message.find_by_tracking_id(params[:message_tracking_id] || params[:tracking_id]) - end -end diff --git a/app/controllers/subscribers_controller.rb b/app/controllers/subscribers_controller.rb deleted file mode 100644 index b00411c..0000000 --- a/app/controllers/subscribers_controller.rb +++ /dev/null @@ -1,48 +0,0 @@ -# frozen_string_literal: true - -class SubscribersController < ApplicationController - before_action :authenticate_user! - before_action :set_subscriber, only: %i[show edit update] - before_action :set_client, only: %i[index] - - def index - @subscribers = @client.subscribers.order(created_at: :desc).page(params[:page]) - end - - def new - @subscriber = Subscriber.new(client_id: params[:client_id]) - end - - def create - @subscriber = Subscriber.new(subscriber_params) - if @subscriber.save - flash["success"] = t("created") - redirect_to client_subscribers_path(@subscriber.client_id) - else - render "new", status: :unprocessable_entity - end - end - - def update - if @subscriber.update(subscriber_params) - flash["success"] = t("updated") - redirect_to client_subscribers_path(@subscriber.client_id) - else - render "edit", status: :unprocessable_entity - end - end - - private - - def set_client - @client = Client.find(params[:client_id]) - end - - def set_subscriber - @subscriber = Subscriber.find params[:id] - end - - def subscriber_params - params.require(:subscriber).permit(:client_id, :name, :address) - end -end diff --git a/app/controllers/subscriptions_controller.rb b/app/controllers/subscriptions_controller.rb deleted file mode 100644 index 2f960b6..0000000 --- a/app/controllers/subscriptions_controller.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -class SubscriptionsController < ApplicationController - before_action :authenticate_user! - before_action :set_subscription, only: %i[edit update] - - def index - @subscriptions = Subscription.includes(:subscriber, :topic).order(created_at: :desc).page(params[:page]) - end - - def update - if @subscription.update(subscription_params) - flash["success"] = t("updated") - redirect_to edit_subscription_path(@subscription.client_id) - else - render "edit", status: :unprocessable_entity - end - end - - private - - def set_subscription - @subscription = Subscription.find params[:id] - end - - def subscription_params - params.require(:subscription).permit(:status, :memo) - end -end diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb deleted file mode 100644 index 1518caf..0000000 --- a/app/controllers/templates_controller.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -class TemplatesController < ApplicationController - before_action :authenticate_user! - before_action :set_template, only: %i[show edit update] - - def new - @template = Template.new(client_id: params[:client_id]) - end - - def create - @template = Template.new(template_params) - if @template.save - flash["success"] = t("created") - redirect_to client_path(@template.client_id) - else - render "new", status: :unprocessable_entity - end - end - - def update - if @template.update(template_params) - flash["success"] = t("updated") - redirect_to client_path(@template.client_id) - else - render "edit", status: :unprocessable_entity - end - end - - private - - def set_template - @template = Template.find params[:id] - end - - def template_params - params.require(:template).permit(:client_id, :name, :sender_name, :sender_address, :html_body, :text_body, - :json_layout, :active) - end -end diff --git a/app/controllers/turbo_controller.rb b/app/controllers/turbo_controller.rb deleted file mode 100644 index 0e1a77c..0000000 --- a/app/controllers/turbo_controller.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -class TurboController < ApplicationController - class Responder < ActionController::Responder - def to_turbo_stream - controller.render(options.merge(formats: :html)) - rescue ActionView::MissingTemplate => e - if get? - raise e - elsif has_errors? && default_action - render rendering_options.merge(formats: :html, status: :unprocessable_entity) - else - redirect_to navigation_location - end - end - end - - self.responder = Responder - respond_to :html, :turbo_stream -end diff --git a/app/forms/adhoc_email_form.rb b/app/forms/adhoc_email_form.rb deleted file mode 100644 index 11f5338..0000000 --- a/app/forms/adhoc_email_form.rb +++ /dev/null @@ -1,77 +0,0 @@ -# frozen_string_literal: true - -class AdhocEmailForm < ApplicationForm - attr_accessor :mailing_topic_id, :send_time, :template_id, :environment_id, :subject, :html_body, :text_body - - def save! - @message = Message.build(mail_params, mailing_topic.client) - - if @message.invalid? - errors.merge! @message.errors - return false - elsif environment.status == "rejected" - errors.add(:base, "Environment is rejected") - return false - end - - receive_and_sort_message - rescue ActiveRecord::StatementInvalid => e - # Handle exception that caused the transaction to fail - # e.message and e.cause.message can be helpful - errors.add(:base, e.message) - - false - end - - private - - def receive_and_sort_message - if @message.received! - MailSortJob.perform_later @message.tracking_id - true - else - false - end - end - - def mail_params - { - bcc: recipients, - environment: environment.name, - html_body: render_html, - sender: template.sender, - subject: subject, - text_body: render_text - } - end - - def render_text - return text_body unless template - - Mustache.render(template.text_body, {body: text_body}) - end - - def render_html - return html_body unless template - - Mustache.render(template.html_body, {body: html_body}) - end - - def recipients - mailing_topic.subscriptions.active.map do |sub| - sub.subscriber.formatted_address - end - end - - def mailing_topic - @mailing_topic ||= MailingTopic.find mailing_topic_id - end - - def template - @template ||= Template.find template_id - end - - def environment - @environment ||= ClientEnvironment.find environment_id - end -end diff --git a/app/forms/application_form.rb b/app/forms/application_form.rb deleted file mode 100644 index 1508c6d..0000000 --- a/app/forms/application_form.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -class ApplicationForm - include ActiveModel::Model -end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb deleted file mode 100644 index 1d94ac3..0000000 --- a/app/helpers/application_helper.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -module ApplicationHelper - include SidebarHelpers - - # Handles HTML title element - def page_title(*titles) - @page_title ||= [] - @page_title.push(*titles.compact) if titles.any? - @page_title.join(" \u00b7 ") # Segments are separated by middot - end - - # Render the error messages for given objects - def error_messages_for(*objects) - objects = objects.map { |o| o.is_a?(String) ? instance_variable_get("@#{o}") : o }.compact - errors = objects.map { |o| o.errors.full_messages }.flatten - render_error_messages(errors) - end - - private - - # Renders a list of error messages - def render_error_messages(errors) - html = "" - if errors.present? - html += "
    \n" - errors.each do |error| - html += "
  • #{h error}
  • \n" - end - html += "

\n" - end - html.html_safe - end -end diff --git a/app/helpers/client_uploads_helper.rb b/app/helpers/client_uploads_helper.rb deleted file mode 100644 index b9f6661..0000000 --- a/app/helpers/client_uploads_helper.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -module ClientUploadsHelper - def file_upload_types - ClientUpload.file_types.to_a.map do |t| - OpenStruct.new(label: ClientUpload.human_enum_name(:file_type, t[0]), value: t[1]) - end - end -end diff --git a/app/helpers/messages_helper.rb b/app/helpers/messages_helper.rb deleted file mode 100644 index 84c04ab..0000000 --- a/app/helpers/messages_helper.rb +++ /dev/null @@ -1,66 +0,0 @@ -# frozen_string_literal: true - -module MessagesHelper - def activity_icon(key) - case key - when "received" - "satellite-dish" - when "rerouted" - "traffic-light" - when "failed" - "minus-octagon" - when "complaint" - "exclamation-triangle" - when "error" - "dumpster-fire" - when "processed" - "badge-check" - when "held" - "pause-circle" - when "ignored" - "ban" - when "opened" - "envelope-open" - when "clicked" - "link" - else - "info-circle" - end - end - - def activity_message(key) - case key - when "received" - "API request recieved" - when "rerouted" - "Rerouted" - when "processed" - "Forwarded to AWS" - when "opened" - "Open" - when "clicked" - "Click" - when "held" - "On Hold" - when "ignored" - "Message Ignored" - else - key - end - end - - def activity_color(key) - case key - when "rerouted", "complaint", "held", "ignored" - "secondary" - when "failed", "error" - "danger" - else - "default" - end - end - - def email_array_to_string(list) - list.map(&:email).join(", ") - end -end diff --git a/app/helpers/subscriptions_helper.rb b/app/helpers/subscriptions_helper.rb deleted file mode 100644 index a4146cc..0000000 --- a/app/helpers/subscriptions_helper.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -module SubscriptionsHelper - def subscription_statuses - Subscription.statuses.to_a.map do |t| - OpenStruct.new(label: Subscription.human_enum_name(:status, t[0]), value: t[1]) - end - end -end diff --git a/app/javascript/application.js b/app/javascript/application.js deleted file mode 100644 index 28e1cb0..0000000 --- a/app/javascript/application.js +++ /dev/null @@ -1,15 +0,0 @@ -import { Application } from "stimulus" -import { definitionsFromContext } from "stimulus/webpack-helpers" - -const application = Application.start() -const context = require.context("controllers", true, /.js$/) -const context_components = require.context("../components", true, /_controller.js$/) -application.load( - definitionsFromContext(context).concat( - definitionsFromContext(context_components) - ) -) - -document.addEventListener('turbo:load', () => { - require("halfmoon").onDOMContentLoaded() -}) diff --git a/app/javascript/controllers/sidebar_controller.js b/app/javascript/controllers/sidebar_controller.js deleted file mode 100644 index 7a39dc8..0000000 --- a/app/javascript/controllers/sidebar_controller.js +++ /dev/null @@ -1,11 +0,0 @@ -import { Controller } from "stimulus" - -export default class extends Controller { - mounted() { - require("halfmoon").onDOMContentLoaded() - } - - toggle() { - require("halfmoon").toggleSidebar() - } -} \ No newline at end of file diff --git a/app/javascript/importmap.json.erb b/app/javascript/importmap.json.erb deleted file mode 100644 index b140236..0000000 --- a/app/javascript/importmap.json.erb +++ /dev/null @@ -1,5 +0,0 @@ -{ - "imports": { - <%= importmap_list_with_stimulus_from "app/javascript/controllers" %> - } -} diff --git a/app/javascript/packs/main.js b/app/javascript/packs/main.js deleted file mode 100644 index e720152..0000000 --- a/app/javascript/packs/main.js +++ /dev/null @@ -1,14 +0,0 @@ -console.log("main.js") - -if (!window.__appClientLoaded) { - window.__appClientLoaded = true - - require('@hotwired/turbo') -} - -require("@rails/ujs").start() -require("trix") -require("@rails/actiontext") -require("@rails/activestorage").start() - -require("application") diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb deleted file mode 100644 index d92ffdd..0000000 --- a/app/jobs/application_job.rb +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true - -class ApplicationJob < ActiveJob::Base -end diff --git a/app/jobs/client_upload_job.rb b/app/jobs/client_upload_job.rb deleted file mode 100644 index 6976c1b..0000000 --- a/app/jobs/client_upload_job.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -class ClientUploadJob < ApplicationJob - def perform(upload_id) - @upload_id = upload_id - return if client_upload.finished? - - client_upload.start! unless client_upload.running? - - data_stream.open do |file| - IO.foreach(file) do |row| - BulkUpload::SubscriberImporter.process(row) - rescue => e - Sentry.capture_exception e - end - end - - client_upload.finish! - end - - private - - def client_upload - @client_upload ||= ClientUpload.find @upload_id - end - - def data_stream - @client_upload.data_file.blob - end -end diff --git a/app/jobs/mail_sort_job.rb b/app/jobs/mail_sort_job.rb deleted file mode 100644 index 407bc28..0000000 --- a/app/jobs/mail_sort_job.rb +++ /dev/null @@ -1,77 +0,0 @@ -# frozen_string_literal: true - -# Takes a MessageID and begins inital sorting of the message -class MailSortJob < ApplicationJob - def perform(tracking_id) - @tracking_id = tracking_id - - ActiveRecord::Base.transaction do - if message.text_body.blank? - message.text_body = PlainText.from_html(message.html_body) - message.save! - end - - if emails_are_rerouted? - reroute_message - # elsif emails_are_whitelisted? - # remove_non_whitelisted_recipients - end - end - - return message.held! if emails_are_held? - return message.ignored! if emails_are_ignored? - - PostalWorkerJob.perform_later(tracking_id) - end - - private - - def message - @message ||= Message.find_by_tracking_id @tracking_id - end - - def remove_non_whitelisted_recipients - whitelisted_emails = [] - message.recipients.where.not(email: whitelisted_emails).destroy_all - end - - def reroute_message - # prevent us from changing the subject and body twice - return if message.rerouted? - - message.html_body = rerouted_body("html") - message.text_body = rerouted_body("text") - message.subject = "[REROUTED] #{message.subject}" - message.sender = ApplicationMailer::DEFAULT_FROM - message.recipients.destroy_all - message.recipients << message.client.reroute_recipient - message.rerouted! - end - - def rerouted_body(type) - template = ApplicationController.render( - template: "api_mailer/reroute_message.#{type}", - assigns: {message: message}, - layout: false - ) - return template unless type == "html" - - message.html_body.html_safe.gsub(/^*]*>/, "\\0 #{template}") - end - - def emails_are_rerouted? - message.client_environment.status == "rerouted" - end - - def emails_are_whitelisted? - message.client_environment.status == "whitelisted" - end - - def emails_are_held? - message.client_environment.status == "hold" - end - - def emails_are_ignored? - message.client_environment.status == "ignored" - end -end diff --git a/app/jobs/postal_worker_job.rb b/app/jobs/postal_worker_job.rb deleted file mode 100644 index 30f488e..0000000 --- a/app/jobs/postal_worker_job.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true - -# Takes a MessageID and sends the message to the approperate destination -class PostalWorkerJob < ApplicationJob - def perform(tracking_id) - @tracking_id = tracking_id - - return if message.sent? - - message.recipients.each do |r| - ApiMailer.with(message: build_params(message, r)) - .send_message - .deliver_now - end - - message.processed! - end - - private - - def message - @message ||= Message.includes(:recipients).find_by_tracking_id @tracking_id - end - - def build_params(message, recipient) - OpenStruct.new( - from: message.sender ||= ApplicationMailer::DEFAULT_FROM, - html_body: message.html_body, - priority: message.priority, - # reply_to: ApplicationMailer::DEFAULT_REPLY, - subject: message.subject, - text_body: message.text_body, - to: recipient.email, - tracking_id: message.tracking_id - ) - end -end diff --git a/app/mailers/api_mailer.rb b/app/mailers/api_mailer.rb deleted file mode 100644 index f1c9dfb..0000000 --- a/app/mailers/api_mailer.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -class ApiMailer < ApplicationMailer - def send_message - @message = params[:message] - append_hermes_headers - - mail(mail_headers) do |format| - format.html { render plain: @message.html_body } - format.text { render plain: @message.text_body } - end - end - - private - - def append_hermes_headers - headers 'X-Hermes-ID': @message.tracking_id - headers 'X-Priority': "1", Importance: "high" if @message.priority.present? - headers 'X-SES-CONFIGURATION-SET': ENV["SES_CONFIGSET"] || "Hermes" - end - - def mail_headers - { - subject: @message.subject, - from: @message.from, - reply_to: @message.from, - to: @message.to - } - end -end diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb deleted file mode 100644 index 405cb14..0000000 --- a/app/mailers/application_mailer.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -class ApplicationMailer < ActionMailer::Base - DEFAULT_FROM = "Hermes " - DEFAULT_REPLY = "MythCoders Support " - - default from: DEFAULT_FROM - layout "mailer" - # headers 'X-SES-CONFIGURATION-SET': 'Hermes' -end diff --git a/app/models/application_record.rb b/app/models/application_record.rb deleted file mode 100644 index 5301771..0000000 --- a/app/models/application_record.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -class ApplicationRecord < ActiveRecord::Base - self.abstract_class = true - - ACTIVITY_TYPES = %i[received rerouted processed sent delivered failed error clicked held ignored].freeze - RECIPIENT_TYPES = %i[to cc bcc].freeze - - def self.human_enum_name(enum_name, enum_value) - I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}") - end -end diff --git a/app/models/callback.rb b/app/models/callback.rb deleted file mode 100644 index 23ca395..0000000 --- a/app/models/callback.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -class Callback < ApplicationRecord - include AASM - - aasm column: :status do - state :created, initial: true - state :errored, :finished - - event :error do - transitions from: %i[created], to: :errored - end - - event :finish do - transitions from: %i[created errored], to: :finished - end - end -end diff --git a/app/models/client.rb b/app/models/client.rb deleted file mode 100644 index 1e232a3..0000000 --- a/app/models/client.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -class Client < ApplicationRecord - has_many :environments, class_name: "ClientEnvironment", dependent: :destroy - has_many :messages - has_many :subscribers - has_many :templates, dependent: :destroy - has_many :topics, class_name: "MailingTopic", dependent: :destroy - has_many :uploads, class_name: "ClientUpload", dependent: :destroy - - validates_length_of :name, :owner, maximum: 50 - validates_length_of :reroute_email, :reply_to_email, maximum: 60 - validates_length_of :api_secret, :api_key, maximum: 128 - validates_uniqueness_of :name, :api_secret, :api_key - validates_presence_of :name, :owner, :reroute_email, :api_secret, :api_key - - def self.authenticate(key, secret) - where(api_key: key, api_secret: secret).limit(1).first - end - - def reroute_recipient - MessageRecipient.new(email: "#{owner} <#{reroute_email}>", recipient_type: :to) - end -end diff --git a/app/models/client_environment.rb b/app/models/client_environment.rb deleted file mode 100644 index 93831a8..0000000 --- a/app/models/client_environment.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -class ClientEnvironment < ApplicationRecord - belongs_to :client, inverse_of: :environments - - validates :name, presence: true, uniqueness: {scope: %i[client]} - - # approved: Messages are delivered without any filtering - # hold: Messages are saved but not delivered - # ignored: Messages are not saved but no error is returned - # rejected: Messages are not saved and an error is returned - # rerouted: Messages are sent to the Client owner - # whitelisted: Messages are only delivered to recipeints whitelisted for the Client - enum status: { - approved: "approved", - hold: "hold", - ignored: "ignored", - rejected: "rejected", - rerouted: "rerouted", - whitelisted: "whitelisted" - } - - def fancy_name - "#{name} (#{status})" - end - - def self.find_or_create_by_env!(client_id, env_name) - direct_match = find_or_initialize_by(client_id: client_id, name: env_name, regex: false) - return direct_match if direct_match.persisted? - - where(client_id: client_id, regex: true).each do |env| - return env if env_name.match(env.name) - end - - direct_match.update!(status: :rerouted) - direct_match - end -end diff --git a/app/models/client_upload.rb b/app/models/client_upload.rb deleted file mode 100644 index dcd9ccb..0000000 --- a/app/models/client_upload.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -class ClientUpload < ApplicationRecord - include AASM - after_create :process_upload - - belongs_to :client, inverse_of: :uploads - has_one_attached :data_file - - validates_presence_of :client, :file_type - - enum file_type: { - subscriber: "subscriber" - } - - aasm column: :status do - state :created, initial: true - state :running, :errored, :finished - - event :start do - transitions from: %i[created], to: :running - end - - event :error do - transitions from: %i[running created], to: :errored - end - - event :finish do - transitions from: %i[running errored], to: :finished - end - end - - private - - def process_upload - ClientUploadJob.perform_later id - end -end diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/app/models/mailing_topic.rb b/app/models/mailing_topic.rb deleted file mode 100644 index e5ec171..0000000 --- a/app/models/mailing_topic.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -class MailingTopic < ApplicationRecord - belongs_to :client - has_many :subscriptions - - scope :active, -> { where(active: true) } - - validates_presence_of :client - validates :name, presence: true, uniqueness: {scope: %i[client]} -end diff --git a/app/models/message.rb b/app/models/message.rb deleted file mode 100644 index 1bf41b3..0000000 --- a/app/models/message.rb +++ /dev/null @@ -1,53 +0,0 @@ -# frozen_string_literal: true - -class Message < ApplicationRecord - belongs_to :client - has_many :recipients, class_name: "MessageRecipient" - has_many :activities, class_name: "MessageActivity" - validates_presence_of :sender, :subject, :client, :environment, :tracking_id - validates_presence_of :recipients, validates_associated: :recipients - - def self.build(params, client) - new(client: client).tap do |message| - message.environment = params[:environment] - message.html_body = params[:html_body] - message.priority = params[:priority] - message.sender = params[:sender] - message.subject = params[:subject] - message.text_body = params[:text_body] - message.tracking_id = SecureRandom.uuid - message.recipients << MessageRecipient.build_from_array(params[:to], :to) if params[:to].present? - message.recipients << MessageRecipient.build_from_array(params[:cc], :cc) if params[:cc].present? - message.recipients << MessageRecipient.build_from_array(params[:bcc], :bcc) if params[:bcc].present? - end - end - - ACTIVITY_TYPES.each do |type| - define_method "#{type}?" do - activities.where(activity_type: type).any? - end - - define_method "#{type}!" do |timestamp = Time.zone.now| - activities << MessageActivity.new(activity_type: type, notification_timestamp: timestamp) - save! - end - end - - RECIPIENT_TYPES.each do |type| - define_method type.to_s do - recipients.where(recipient_type: type) - end - end - - def system_activity - activities.where(activity_type: %w[received held ignored rerouted processed]) - end - - def user_activity - activities.where(activity_type: %w[clicked opened]) - end - - def client_environment - @client_environment ||= ClientEnvironment.find_or_create_by_env!(client_id, environment) - end -end diff --git a/app/models/message_activity.rb b/app/models/message_activity.rb deleted file mode 100644 index 5f292d3..0000000 --- a/app/models/message_activity.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -class MessageActivity < ApplicationRecord - belongs_to :message - has_many :message_activity_recipients - has_many :recipients, through: :message_activity_recipients, source: :message_recipient - - def recipient - recipients.first - end -end diff --git a/app/models/message_activity_recipient.rb b/app/models/message_activity_recipient.rb deleted file mode 100644 index c366750..0000000 --- a/app/models/message_activity_recipient.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -class MessageActivityRecipient < ApplicationRecord - belongs_to :message_recipient - belongs_to :message_activity -end diff --git a/app/models/message_recipient.rb b/app/models/message_recipient.rb deleted file mode 100644 index 13cb1d4..0000000 --- a/app/models/message_recipient.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -class MessageRecipient < ApplicationRecord - RECIPIENT_TYPES = %i[to cc bcc].freeze - - belongs_to :message - has_many :message_activity_recipients - has_many :activities, through: :message_activity_recipients, source: :message_activity - - def self.build_from_array(list, type) - list.map do |item| - new(email: item, - recipient_type: type) - end - end -end diff --git a/app/models/subscriber.rb b/app/models/subscriber.rb deleted file mode 100644 index 08e23b8..0000000 --- a/app/models/subscriber.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -class Subscriber < ApplicationRecord - belongs_to :client - has_many :subscriptions - - validates_presence_of :client - validates :address, presence: true, uniqueness: {scope: %i[client]} - - def formatted_address - "#{name} <#{address}>" - end -end diff --git a/app/models/subscription.rb b/app/models/subscription.rb deleted file mode 100644 index 7faa13d..0000000 --- a/app/models/subscription.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -class Subscription < ApplicationRecord - belongs_to :topic, class_name: "MailingTopic", foreign_key: "mailing_topic_id" - belongs_to :subscriber, autosave: true - - enum status: { - inactive: 0, - active: 1, - paused: 2 - } - - validates_presence_of :topic, :status, :identifier - validates :subscriber, presence: true, uniqueness: {scope: %i[topic]} -end diff --git a/app/models/template.rb b/app/models/template.rb deleted file mode 100644 index b30ecad..0000000 --- a/app/models/template.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -class Template < ApplicationRecord - belongs_to :client - - scope :active, -> { where(active: true) } - - validates_presence_of :client - validates_presence_of :sender_name, :sender_address, :html_body, :text_body, if: :active - validates :name, presence: true, uniqueness: {scope: %i[client]} - - def sender - "#{sender_name} <#{sender_address}>" - end -end diff --git a/app/models/user.rb b/app/models/user.rb deleted file mode 100644 index 02e6ab0..0000000 --- a/app/models/user.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -class User < ApplicationRecord - devise :database_authenticatable, :registerable, :recoverable, - :rememberable, :trackable, :validatable, :confirmable, - :lockable, :timeoutable - - validate :email_domain_is_mythcoders - - def email_domain - email.split("@").last - end - - def initials - name.split.map(&:first).join - end - - private - - def email_domain_is_mythcoders - return if email_domain.nil? || email_domain == "mythcoders.com" - - Sentry.capture_message("Signup for non-mythcoders account", level: "warning") - errors.add(:email, "Registrations for this domain have not been approved") - end -end diff --git a/app/views/active_storage/blobs/_blob.html.erb b/app/views/active_storage/blobs/_blob.html.erb deleted file mode 100644 index 49ba357..0000000 --- a/app/views/active_storage/blobs/_blob.html.erb +++ /dev/null @@ -1,14 +0,0 @@ -
attachment--<%= blob.filename.extension %>"> - <% if blob.representable? %> - <%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %> - <% end %> - -
- <% if caption = blob.try(:caption) %> - <%= caption %> - <% else %> - <%= blob.filename %> - <%= number_to_human_size blob.byte_size %> - <% end %> -
-
diff --git a/app/views/api_mailer/reroute_message.html.haml b/app/views/api_mailer/reroute_message.html.haml deleted file mode 100644 index d9e6fd5..0000000 --- a/app/views/api_mailer/reroute_message.html.haml +++ /dev/null @@ -1,34 +0,0 @@ -%p= t('rerouted') -%table - %tr - %td - %strong CLIENT: - %td= "#{@message.client.name} - #{@message.environment}" - %tr - %td - %strong SUBJECT: - %td - = @message.subject - %tr - %td - %strong FROM: - %td - = @message.sender - %tr - %td - %strong TO: - %td - = email_array_to_string @message.to - - if @message.cc.present? - %tr - %td - %strong CC: - %td - = email_array_to_string @message.cc - - if @message.bcc.present? - %tr - %td - %strong BCC: - %td - = email_array_to_string @message.bcc -%br diff --git a/app/views/api_mailer/reroute_message.text.erb b/app/views/api_mailer/reroute_message.text.erb deleted file mode 100644 index ed9eea7..0000000 --- a/app/views/api_mailer/reroute_message.text.erb +++ /dev/null @@ -1,16 +0,0 @@ -<%= t('rerouted') %> - -CLIENT: <%= @message.client.name %> - <%= @message.environment %> -SUBJECT: <%= @message.subject %> -FROM: <%= @message.sender %> -TO: <%= email_array_to_string @message.to %> - -<% if @message.cc.present? %> - CC: <%= email_array_to_string @message.cc %> -<% end %> - -<% if @message.bcc.present? %> - BCC: <%= email_array_to_string @message.bcc %> -<% end %> - -<%= raw @message.text_body %> diff --git a/app/views/api_mailer/send_message.html.haml b/app/views/api_mailer/send_message.html.haml deleted file mode 100644 index f2be5ab..0000000 --- a/app/views/api_mailer/send_message.html.haml +++ /dev/null @@ -1 +0,0 @@ -= @message.html_body.html_safe diff --git a/app/views/api_mailer/send_message.text.haml b/app/views/api_mailer/send_message.text.haml deleted file mode 100644 index 93da7cb..0000000 --- a/app/views/api_mailer/send_message.text.haml +++ /dev/null @@ -1 +0,0 @@ -= @message.text_body diff --git a/app/views/client_environments/_form.html.haml b/app/views/client_environments/_form.html.haml deleted file mode 100644 index 3608b9c..0000000 --- a/app/views/client_environments/_form.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -= f.hidden_field :id -= f.hidden_field :client_id - -.form-row - .form-group.col - = f.label :name, class: 'col-form-label' - = f.text_field :name, class: 'form-control' - .form-group.col - = f.label :status, class: 'col-form-label' - = f.select :status, ClientEnvironment.statuses.map { |key, value| [key.humanize, key] }, {}, {class: 'form-control'} -.form-group.custom-control.custom-switch - = f.check_box :regex, class: 'custom-control-input' - = f.label :regex, class: 'custom-control-label' \ No newline at end of file diff --git a/app/views/client_environments/edit.html.haml b/app/views/client_environments/edit.html.haml deleted file mode 100644 index e9c85d5..0000000 --- a/app/views/client_environments/edit.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- page_title 'Edit', 'Template' - -.content - %h1.card-title - %i.fas.fa-key-skeleton - = "Edit #{@environment.name}" - - = form_for @environment, url: client_environment_path(@environment), method: :patch do |f| - = error_messages_for 'environment' - = render partial: 'client_environments/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', client_path(@environment.client), class: 'btn alt-dm' - = f.submit 'Save changes', class: 'btn btn-success float-right' diff --git a/app/views/client_environments/new.html.haml b/app/views/client_environments/new.html.haml deleted file mode 100644 index f3b7bac..0000000 --- a/app/views/client_environments/new.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- page_title 'New', 'API Permissions' - -.content - %h1.content-title - %i.fas.fa-key-skeleton - Create a new API Permission - - = form_for @environment, url: client_environments_path do |f| - = error_messages_for 'environment' - = render partial: 'client_environments/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', client_path(@environment.client), class: 'btn alt-dm' - = f.submit 'Create', class: 'btn btn-success float-right' diff --git a/app/views/client_uploads/new.html.haml b/app/views/client_uploads/new.html.haml deleted file mode 100644 index 57863b6..0000000 --- a/app/views/client_uploads/new.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -- page_title 'New', 'Upload' - -.content - %h1.card-title - %i.fas.fa-file-import - Create a new Upload - - = form_for @upload, url: client_uploads_path, method: :post do |f| - = error_messages_for 'upload' - - = f.hidden_field :id - = f.hidden_field :client_id - - .form-group - = f.label :file_type, class: 'col-form-label' - = f.select :file_type, - options_from_collection_for_select(file_upload_types, 'value', 'label'), - { include_blank: '- Select -' }, - { class: 'form-control' } - - .form-group - .custom-file - = f.file_field :file, accept: 'text/csv', class: 'custom-file-input' - = f.label :file, class: 'custom-file-label' - - %hr.mt-5.mb-5 - = link_to 'Cancel', client_path(@upload.client_id), class: 'btn alt-dm' - = f.submit 'Upload', class: 'btn btn-success float-right' \ No newline at end of file diff --git a/app/views/clients/_environments.html.haml b/app/views/clients/_environments.html.haml deleted file mode 100644 index a39bbce..0000000 --- a/app/views/clients/_environments.html.haml +++ /dev/null @@ -1,37 +0,0 @@ -.card.p-0 - .px-card.py-10.bg-very-dark-dm - .row - .col - %h2.card-title.font-size-18.m-0 - %i.fas.fa-key-skeleton - API Environments - .col-auto - %a.btn.btn-sm{href: new_client_environment_path(@client)} - New - - if @client.environments.any? - .table-responsive - %table.table - %thead - %tr - %th Name - %th.float-right Delivery Policy - %tbody - - @client.environments.order(:name).each do |e| - %tr - %td - = link_to e.name, edit_client_environment_path(@client, e) - - if e.regex? - %span.badge.text-uppercase Regex - %td.float-right - - if e.status == 'approved' - %span.badge.badge-success.text-uppercase= e.status - - elsif e.status == 'rejected' - %span.badge.badge-danger.text-uppercase= e.status - - elsif e.status == 'hold' - %span.badge.badge-secondary.text-uppercase= e.status - - else - %span.badge.text-uppercase= e.status - - else - .text-center - %h3.content-title.mt-10 No Environments - %p.text-muted This client does not have permissions in any environments. \ No newline at end of file diff --git a/app/views/clients/_form.html.haml b/app/views/clients/_form.html.haml deleted file mode 100644 index d0a3408..0000000 --- a/app/views/clients/_form.html.haml +++ /dev/null @@ -1,29 +0,0 @@ -= f.hidden_field :id -.form-row - .form-group.col-12.col-lg-6 - = f.label :name, class: 'col-form-label' - = f.text_field :name, class: 'form-control' - .form-group.col-12.col-lg-6 - = f.label :owner, class: 'col-form-label' - = f.text_field :owner, class: 'form-control' -.form-row - .form-group.col-12.col-lg-6 - = f.label :reroute_email, class: 'col-form-label' - = f.text_field :reroute_email, class: 'form-control' - .form-group.col-12.col-lg-6 - = f.label :reply_to_email, class: 'col-form-label' - = f.text_field :reply_to_email, class: 'form-control' -.form-group - = f.label :api_secret, class: 'col-form-label' - = f.text_field :api_secret, class: 'form-control' -.form-group - = f.label :api_key, class: 'col-form-label' - = f.text_field :api_key, class: 'form-control' -%hr.mt-5.mb-5 -.row - .col-12.col-md-6 - %h4.mb-4 - Options - .form-group.custom-control.custom-switch - = f.check_box :is_active, class: 'custom-control-input' - = f.label :is_active, class: 'custom-control-label' diff --git a/app/views/clients/_header.html.haml b/app/views/clients/_header.html.haml deleted file mode 100644 index c094edf..0000000 --- a/app/views/clients/_header.html.haml +++ /dev/null @@ -1,19 +0,0 @@ -.content.mb-0 - .row - .col - %h1.content-title.font-size-22 - %i.fas.fa-code - = @client.name - %a.btn{href: client_path(@client), class: ('alt-dm' if action != :summary)} Summary - %a.btn{href: client_messages_path(@client), class: ('alt-dm' if action != :messages)} - %i.fas.fa-stream - Messages - %a.btn{href: client_subscribers_path(@client), class: ('alt-dm' if action != :subscribers)} - %i.fas.fa-users - Subscribers - .col-auto - .btn-group - = link_to 'All Clients', clients_path, class: 'btn alt-dm' - - if @client.environments.any? - = link_to 'Send Email', client_new_email_path(@client), class: 'btn alt-dm' - = link_to 'Edit', edit_client_path(@client), class: 'btn btn-primary' \ No newline at end of file diff --git a/app/views/clients/_overview.html.haml b/app/views/clients/_overview.html.haml deleted file mode 100644 index f92647d..0000000 --- a/app/views/clients/_overview.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -.card.p-15 - .row.align-items-center - .col - %strong Owner - .col-auto - .text-muted= @client.owner - %hr - .row.align-items-center - .col - %strong Reroute Email - .col-auto - .text-muted= mail_to @client.reroute_email - - if @client.reply_to_email - %hr - .row.align-items-center - .col - %strong Default Reply Email - .col-auto - .text-muted= @client.reply_to_email - %hr - .row.align-items-center - .col - %strong API Access - .col-auto - - if @client.is_active - %span.badge.badge-success.text-uppercase approved - - else - %span.badge.badge-danger.text-uppercase blocked \ No newline at end of file diff --git a/app/views/clients/_templates.html.haml b/app/views/clients/_templates.html.haml deleted file mode 100644 index 1c36266..0000000 --- a/app/views/clients/_templates.html.haml +++ /dev/null @@ -1,30 +0,0 @@ -.card.p-0 - .px-card.py-10.bg-very-dark-dm - .row - .col - %h2.card-title.font-size-18.m-0 - %i.fas.fa-object-group - Templates - .col-auto - %a.btn.btn-sm{href: new_client_template_path(@client)} - New - - if @client.templates.any? - .table-responsive - %table.table.card-table - %thead - %tr - %th Name - %th.float-right Status - %tbody - - @client.templates.order(:name).each do |t| - %tr - %td= link_to t.name, client_template_path(@client, t) - %td.float-right - - if t.active - %span.badge.badge-success.text-uppercase active - - else - %span.badge.badge-secondary.text-uppercase inactive - - else - .text-center - %h3.content-title.mt-10 No Templates - %p.text-muted This client does not have any email templates saved. \ No newline at end of file diff --git a/app/views/clients/_topics.html.haml b/app/views/clients/_topics.html.haml deleted file mode 100644 index cb8c6e0..0000000 --- a/app/views/clients/_topics.html.haml +++ /dev/null @@ -1,32 +0,0 @@ -.card.p-0 - .px-card.py-10.bg-very-dark-dm - .row - .col - %h2.card-title.font-size-18.m-0 - %i.fas.fa-clipboard-list - Mailing Topics - .col-auto - %a.btn.btn-sm{href: new_client_topic_path(@client)} - New - - if @client.topics.any? - .table-responsive - %table.table.card-table - %thead - %tr - %th Name - %th Size - %th.float-right Status - %tbody - - @client.topics.order(:name).each do |t| - %tr - %td= link_to t.name, edit_client_topic_path(@client, t) - %td= t.subscriptions.count - %td.float-right - - if t.active - %span.badge.badge-success.text-uppercase active - - else - %span.badge.badge-secondary.text-uppercase inactive - - else - .text-center - %h3.content-title.mt-10 No Topics - %p.text-muted This client does not have any topics saved. \ No newline at end of file diff --git a/app/views/clients/_uploads.html.haml b/app/views/clients/_uploads.html.haml deleted file mode 100644 index 924d939..0000000 --- a/app/views/clients/_uploads.html.haml +++ /dev/null @@ -1,29 +0,0 @@ -.card.p-0 - .px-card.py-10.bg-very-dark-dm - .row - .col - %h2.card-title.font-size-18.m-0 - %i.fas.fa-file-import - Uploads - .col-auto - %a.btn.btn-sm{href: new_client_upload_path(@client)} - New - - if @client.uploads.any? - .table-responsive - %table.table - %thead - %tr - %th Type - %th Date - %th.float-right Status - %tbody - - @client.uploads.order(created_at: :desc).each do |t| - %tr - %td= ClientUpload.human_enum_name :file_types, t.file_type - %td= l t.created_at - %td.float-right - %span.badge.text-uppercase= t.status - - else - .text-center - %h3.content-title.mt-10 No Uploads - %p.text-muted This client does not have any files uploaded yet. \ No newline at end of file diff --git a/app/views/clients/edit.html.haml b/app/views/clients/edit.html.haml deleted file mode 100644 index 801a53d..0000000 --- a/app/views/clients/edit.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -- page_title 'Edit', 'Client' - -.content - %h1.content-title - %i.fas.fa-code - = "Edit #{@client.name}" - - = form_for @client, url: client_path(@client), method: :patch do |f| - = error_messages_for 'client' - = render partial: 'clients/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', client_path(@client), class: 'btn alt-dm' - = f.submit 'Save changes', class: 'btn btn-success float-right' - diff --git a/app/views/clients/index.html.haml b/app/views/clients/index.html.haml deleted file mode 100644 index 1a15c08..0000000 --- a/app/views/clients/index.html.haml +++ /dev/null @@ -1,32 +0,0 @@ -- page_title 'Client Search' - -.content - .row - .col - %h1.content-title.font-size-22 - %i.fas.fa-code - Clients - .col-auto - = link_to 'New Client', new_client_path, class: 'btn btn-primary lift' - -.card.p-0 - .table-responsive - %table.table.card-table - %thead - %tr - %th Name - %th Owner - %th.float-right API Access - %tbody - - @clients.each do |c| - %tr - %td= link_to c.name, client_path(c) - %td= c.owner - %td.float-right - - if c.is_active - %span.badge.badge-success.text-uppercase Approved - - else - %span.badge.badge-danger.text-uppercase Blocked - .p-10 - = paginate @clients - = page_entries_info @clients diff --git a/app/views/clients/messages.html.haml b/app/views/clients/messages.html.haml deleted file mode 100644 index a7952e0..0000000 --- a/app/views/clients/messages.html.haml +++ /dev/null @@ -1,43 +0,0 @@ -- page_title @client.name, 'Client' - -= render partial: 'header', locals: { action: :messages } - -.row - .col-12.col-md-4 - = render partial: 'overview' - - .col-12.col-md-8 - .card.p-0 - .px-card.py-10.bg-very-dark-dm - .row - .col - %h2.card-title.font-size-18.m-0 - %i.fas.fa-stream - Messages - - if @client.environments.any? - .col-auto - %a.btn.btn-sm{href: client_new_email_path(@client)} - New - - if @messages.any? - .table-responsive - %table.table.card-table - %thead - %tr - %th Timestamp - %th Subject - %th Env - %tbody - - @messages.each do |m| - %tr - %td= link_to l(m.created_at), message_path(m.tracking_id) - %td= m.subject - %td - %span.badge.text-monospace= m.environment - .p-10 - = paginate @messages - = page_entries_info @messages - - else - .text-center - %h3.content-title.mt-10 No Messages - %p.text-muted This client does not have any email templates saved. - diff --git a/app/views/clients/new.html.haml b/app/views/clients/new.html.haml deleted file mode 100644 index a47236f..0000000 --- a/app/views/clients/new.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- page_title 'New', 'Client' - -.content - %h1.content-title - %i.fas.fa-code - Create a new client - - = form_for @client, url: clients_path do |f| - = error_messages_for 'client' - = render partial: 'clients/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', clients_path, class: 'btn alt-dm' - = f.submit 'Create', class: 'btn btn-success float-right' diff --git a/app/views/clients/new_email.html.haml b/app/views/clients/new_email.html.haml deleted file mode 100644 index 29101ec..0000000 --- a/app/views/clients/new_email.html.haml +++ /dev/null @@ -1,52 +0,0 @@ -- page_title 'Send Email' - -.content - %h1.content-title - %i.fas.fa-code - Send Email - - .row.justify-content-center - .col-12.col-lg-10.col-xl-8 - = form_for @message, url: client_send_email_path(@client), html: { id: 'wizardSteps', class: 'tab-content py-6' } do |f| - = error_messages_for 'message' - - .form-group - = f.label :mailing_topic_id, class: 'col-form-label' - = f.select :mailing_topic_id, - options_from_collection_for_select(@client.topics.active, 'id', 'name', @message.mailing_topic_id), - { include_blank: '- Select -' }, - { class: 'form-control', 'data-toggle': 'select' } - -# .form-group - -# = f.label :send_time, class: 'col-form-label' - -# = f.datetime_field :send_time, class: 'form-control' - - .form-group - = f.label :template_id, class: 'col-form-label' - = f.select :template_id, - options_from_collection_for_select(@client.templates.active, 'id', 'name', @message.template_id), - { include_blank: '- Select -' }, - { class: 'form-control', 'data-toggle': 'select' } - - .form-group - = f.label :environment_id, class: 'col-form-label' - = f.select :environment_id, - options_from_collection_for_select(@client.environments.where(regex: false), 'id', 'fancy_name', @message.environment_id), - { include_blank: '- Select -' }, - { class: 'form-control', 'data-toggle': 'select' } - - %hr.my-5 - - .form-group - = f.label :subject, class: 'col-form-label' - = f.text_field :subject, class: 'form-control' - .form-group - = f.label :html_body, class: 'col-form-label' - = f.text_area :html_body, class: 'form-control', rows: 7 - .form-group - = f.label :text_body, class: 'col-form-label' - = f.text_area :text_body, class: 'form-control', rows: 7 - - %hr.my-5 - - = link_to 'Back', client_path(@client), class: 'btn alt-dm' - = f.submit 'Schedule', class: 'btn btn-success float-right' diff --git a/app/views/clients/show.html.haml b/app/views/clients/show.html.haml deleted file mode 100644 index 8fc2928..0000000 --- a/app/views/clients/show.html.haml +++ /dev/null @@ -1,27 +0,0 @@ -- page_title @client.name, 'Client' - -= render partial: 'header', locals: { action: :summary } - -.row - .col-4 - = render partial: 'overview' - - .col-8 - %details.collapse-panel{style: "margin: 30px"} - %summary.collapse-header.bg-very-dark-dm.font-size-18 - %i.fas.fa-key-skeleton - API Credentials - .collapse-content.p-0 - .table-responsive - %table.table.p-0 - %tbody - %tr - %td{style: "width: 5%"} Key/Username - %td.text-monospace= @client.api_key - %tr - %td{style: "width: 5%"} Secret/Password - %td.text-monospace= @client.api_secret - = render partial: 'environments' - = render partial: 'topics' - = render partial: 'templates' - = render partial: 'uploads' diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml deleted file mode 100644 index 0231bcd..0000000 --- a/app/views/devise/confirmations/new.html.haml +++ /dev/null @@ -1,18 +0,0 @@ -- content_for :header do - Resend Account Confirmation - -= render partial: 'devise/shared/error_messages' - -= form_for(resource, as: resource_name, url: confirmation_path(resource_name), :html => { :method => :post, class: '', "data-turbo": "false" }) do |f| - .form-group - = f.email_field :email, autofocus: true, value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email), class: 'form-control', :placeholder => 'Email Address' - - = f.submit 'Resend', class: 'btn btn-primary btn-block btn-login' - - .text-center.mt-10 - Already have an account? - = link_to 'Sign in.', new_session_path(resource_name) - - if devise_mapping.recoverable? - %br - Forgot your password? - = link_to 'Reset it.', new_password_path(resource_name) diff --git a/app/views/devise/mailer/confirmation_instructions.html.haml b/app/views/devise/mailer/confirmation_instructions.html.haml deleted file mode 100644 index 8a24698..0000000 --- a/app/views/devise/mailer/confirmation_instructions.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -%h2 Hermes -%p= "Welcome #{@email}!" -%p You can confirm your account email through the link below: -%p= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) diff --git a/app/views/devise/mailer/password_change.html.erb b/app/views/devise/mailer/password_change.html.erb deleted file mode 100644 index b41daf4..0000000 --- a/app/views/devise/mailer/password_change.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -

Hello <%= @resource.email %>!

- -

We're contacting you to notify you that your password has been changed.

diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb deleted file mode 100644 index f667dc1..0000000 --- a/app/views/devise/mailer/reset_password_instructions.html.erb +++ /dev/null @@ -1,8 +0,0 @@ -

Hello <%= @resource.email %>!

- -

Someone has requested a link to change your password. You can do this through the link below.

- -

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

- -

If you didn't request this, please ignore this email.

-

Your password won't change until you access the link above and create a new one.

diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb deleted file mode 100644 index 41e148b..0000000 --- a/app/views/devise/mailer/unlock_instructions.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -

Hello <%= @resource.email %>!

- -

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

- -

Click the link below to unlock your account:

- -

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml deleted file mode 100644 index f665121..0000000 --- a/app/views/devise/passwords/edit.html.haml +++ /dev/null @@ -1,18 +0,0 @@ -- content_for :header do - Change your password - -= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put, "data-turbo": "false" }) do |f| - = render partial: 'devise/shared/error_messages' - = f.hidden_field :reset_password_token - .form-group - = f.label :password, 'New password' - - if @minimum_password_length - %em="#{@minimum_password_length} characters minimum" - = f.password_field :password, autofocus: true, class: 'form-control', autocomplete: 'off' - .form-group - = f.label :password_confirmation, 'Confirm new password' - = f.password_field :password_confirmation, class: 'form-control', autocomplete: 'off' - .form-group - = f.submit 'Change my password', class: 'btn btn-primary btn-block btn-login' - .login-bottom-links - = render 'devise/shared/links' \ No newline at end of file diff --git a/app/views/devise/passwords/new.html.haml b/app/views/devise/passwords/new.html.haml deleted file mode 100644 index 59b0be1..0000000 --- a/app/views/devise/passwords/new.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- content_for :header do - Forgot Password - -= render partial: 'devise/shared/error_messages' -= form_for(resource, as: resource_name, url: password_path(resource_name), :html => { :method => :post, "data-turbo": "false" }) do |f| - .form-group - = f.email_field :email, autofocus: true, class: 'form-control', :placeholder => 'Email Address' - - = f.submit 'Send reset instructions', class: 'btn btn-primary btn-block' - - .text-center.mt-10 - Remember your password? - = link_to 'Sign in', new_session_path(resource_name) \ No newline at end of file diff --git a/app/views/devise/registrations/edit.html.haml b/app/views/devise/registrations/edit.html.haml deleted file mode 100644 index 1620183..0000000 --- a/app/views/devise/registrations/edit.html.haml +++ /dev/null @@ -1,27 +0,0 @@ -- content_for :header do - My Profile - -= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put, "data-turbo": "false" }) do |f| - = render partial: 'devise/shared/error_messages' - - .form-horizontal - .form-group - = f.label :your_name - .input-group - .input-group-prepend - %span.input-group-text - %i.fas.fa-user - = f.text_field :name, class: 'form-control', autofocus: true, autocomplete: 'off' - - .form-group - = f.label :email - = f.email_field :email, class: 'form-control', autocomplete: 'off' - - .form-group - = f.label :current_password - = f.password_field :current_password, autocomplete: 'off', class: 'form-control' - %p.form-text.text-muted - We need your current password to confirm your changes - - = link_to 'Cancel', home_path, class: 'btn btn-secondary' - = f.submit 'Save Changes', class: 'btn btn-success' diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml deleted file mode 100644 index b863f73..0000000 --- a/app/views/devise/registrations/new.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -- content_for :header do - Register for an account - -= render partial: 'devise/shared/error_messages' - -= form_for(resource, as: resource_name, url: registration_path(resource_name), :html => { class: 'form-horizontal', "data-turbo": "false" }) do |f| - .form-group - = f.text_field :name, class: 'form-control', placeholder: 'Full Name', autofocus: true, autocomplete: 'off' - .form-group - = f.email_field :email, autocomplete: 'off', class: 'form-control', :placeholder => 'Email Address' - .form-group - = f.password_field :password, autocomplete: 'off', class: 'form-control', :placeholder => 'Password' - - .form-group - = f.password_field :password_confirmation, autocomplete: 'off', class: 'form-control', :placeholder => 'Password Confirmation' - - - if @minimum_password_length - %br - %strong Password Requirements: - .form-text.text-muted - = @minimum_password_length - characters minimum - - = f.submit 'Sign Up', class: 'btn btn-primary btn-block' - - .text-center.mt-10 - Already have an account? - = link_to 'Sign in.', new_session_path(resource_name) diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml deleted file mode 100644 index 914b065..0000000 --- a/app/views/devise/sessions/new.html.haml +++ /dev/null @@ -1,30 +0,0 @@ -- content_for :header do - Sign in - -= form_for resource, as: resource_name, url: session_path(resource_name), html: { "data-turbo": "false" } do |f| - = render partial: 'devise/shared/error_messages' - - .form-group - = f.email_field :email, autofocus: true, class: 'form-control', :placeholder => 'Email Address', autocomplete: false - .form-group - = f.password_field :password, autocomplete: 'off', class: 'form-control', :placeholder => 'Password' - - - if devise_mapping.rememberable? - .form-group - .custom-control.custom-checkbox - = f.check_box :remember_me, class: 'custom-control-input' - %label.custom-control-label{for: 'user_remember_me'} Keep me signed in - - = f.submit 'Proceed', class: 'btn btn-primary btn-block' - - .text-center.mt-15 - - if devise_mapping.recoverable? - Forgot your password? - = link_to 'Reset it.', new_password_path(resource_name) - %br - Don't have an account? - = link_to 'Register today!', new_registration_path(resource_name) - %br - - if devise_mapping.confirmable? - Didn't receive your account confirmation instructions? - = link_to 'Resend it.', new_confirmation_path(resource_name) \ No newline at end of file diff --git a/app/views/devise/shared/_error_messages.html.haml b/app/views/devise/shared/_error_messages.html.haml deleted file mode 100644 index c705c79..0000000 --- a/app/views/devise/shared/_error_messages.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -- if resource.errors.any? - #error_explanation.alert.alert-danger.mb-20 - .mb-5= I18n.t("errors.messages.not_saved", count: resource.errors.count, resource: resource.class.model_name.human.downcase) - %ul - - resource.errors.full_messages.each do |message| - %li= message diff --git a/app/views/devise/shared/_links.html.haml b/app/views/devise/shared/_links.html.haml deleted file mode 100644 index 9a3dce3..0000000 --- a/app/views/devise/shared/_links.html.haml +++ /dev/null @@ -1,24 +0,0 @@ -- if controller_name != 'sessions' - = link_to 'Already have an account? Sign in', new_session_path(resource_name), class: 'card-link' - %br - -- if devise_mapping.registerable? && controller_name != 'registrations' - = link_to 'Sign up for a new account', new_registration_path(resource_name), class: 'card-link' - %br - -- if devise_mapping.recoverable? && controller_name != 'passwords' - = link_to 'Reset your forgotten password', new_password_path(resource_name), class: 'card-link' - %br - -- if devise_mapping.confirmable? && controller_name != 'confirmations' - = link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name), class: 'card-link' - %br - -- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' - = link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name), class: 'card-link' - %br - -- if devise_mapping.omniauthable? - - resource_class.omniauth_providers.each do |provider| - = link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), class: 'card-link' - %br \ No newline at end of file diff --git a/app/views/devise/unlocks/new.html.haml b/app/views/devise/unlocks/new.html.haml deleted file mode 100644 index e07facd..0000000 --- a/app/views/devise/unlocks/new.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -- content_for :header do - Resend unlock instructions - -= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post, "data-turbo": "false" }) do |f| - = render partial: 'devise/shared/error_messages' - .form-group - = f.email_field :email, autofocus: true, class: 'form-control', :placeholder => 'Email Address' - .form-group - = f.submit 'Resend unlock instructions', class: 'btn btn-primary btn-block btn-login' - .login-bottom-links - = render 'devise/shared/links' \ No newline at end of file diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml deleted file mode 100644 index f9d1ac9..0000000 --- a/app/views/home/index.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -.content - %h1.content-title.font-size-22 - %i.fas.fa-analytics - Dashboard - - .my-20 - .card.w-350.mw-full.m-0.p-0.d-flex - .w-60.h-60.m-10.align-self-center - .m-20.w-60.h-60.rounded.d-flex.align-items-center.justify-content-center - .font-size-22= Message.count - .flex-grow-1.d-flex.align-items-center - .p-10.w-full.m-auto - %p.m-0.font-weight-medium Total Messages \ No newline at end of file diff --git a/app/views/kaminari/_first_page.html.haml b/app/views/kaminari/_first_page.html.haml deleted file mode 100644 index ed60523..0000000 --- a/app/views/kaminari/_first_page.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -%li.page-item - %a.page-link{href:url, remote:remote} - = raw(t 'views.pagination.first') \ No newline at end of file diff --git a/app/views/kaminari/_gap.html.haml b/app/views/kaminari/_gap.html.haml deleted file mode 100644 index 8e5f2fb..0000000 --- a/app/views/kaminari/_gap.html.haml +++ /dev/null @@ -1,2 +0,0 @@ -%li.page-item.disabled - = content_tag :span, raw(t 'views.pagination.truncate'), class: 'page-link' \ No newline at end of file diff --git a/app/views/kaminari/_last_page.html.haml b/app/views/kaminari/_last_page.html.haml deleted file mode 100644 index 1139ec9..0000000 --- a/app/views/kaminari/_last_page.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -%li.page-item - %a.page-link{href:url, remote:remote} - = raw(t 'views.pagination.last') \ No newline at end of file diff --git a/app/views/kaminari/_next_page.html.haml b/app/views/kaminari/_next_page.html.haml deleted file mode 100644 index 877f71d..0000000 --- a/app/views/kaminari/_next_page.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -%li.page-item - %a.page-link{href:url, remote:remote, rel:'next'} - = raw(t 'views.pagination.next') \ No newline at end of file diff --git a/app/views/kaminari/_page.html.haml b/app/views/kaminari/_page.html.haml deleted file mode 100644 index 09a7ef8..0000000 --- a/app/views/kaminari/_page.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -- if page.current? - %li.page-item.active - %a.page-link{href:url, remote:remote, rel:(page.next? ? 'next' : (page.prev? ? 'prev' : nil))} - = page -- else - %li.page-item - %a.page-link{href:url, remote:remote, rel:(page.next? ? 'next' : (page.prev? ? 'prev' : nil))} - = page \ No newline at end of file diff --git a/app/views/kaminari/_paginator.html.haml b/app/views/kaminari/_paginator.html.haml deleted file mode 100644 index 1b4f05a..0000000 --- a/app/views/kaminari/_paginator.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -= paginator.render do - %nav - %ul.pagination - = first_page_tag unless current_page.first? - = prev_page_tag unless current_page.first? - - each_page do |page| - - if page.left_outer? || page.right_outer? || page.inside_window? - = page_tag page - - elsif !page.was_truncated? - = gap_tag - = next_page_tag unless current_page.last? - = last_page_tag unless current_page.last? \ No newline at end of file diff --git a/app/views/kaminari/_prev_page.html.haml b/app/views/kaminari/_prev_page.html.haml deleted file mode 100644 index c129c3c..0000000 --- a/app/views/kaminari/_prev_page.html.haml +++ /dev/null @@ -1,3 +0,0 @@ -%li.page-item - %a.page-link{href:url, remote:remote, rel:'prev'} - = raw(t 'views.pagination.previous') \ No newline at end of file diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml deleted file mode 100644 index cc134cd..0000000 --- a/app/views/layouts/application.html.haml +++ /dev/null @@ -1,19 +0,0 @@ -!!! -%html{html_attrs('en-us')} - %head - = render partial: 'layouts/partials/header' - %body.dark-mode{"data-sidebar-type": "overlayed-sm-and-down", - "data-set-preferred-mode-onload": "true", - "data-dm-shortcut-enabled": "true", - "data-sidebar-shortcut-enabled": "true"} - .page-wrapper.with-navbar.with-sidebar.with-transitions - = render partial: 'layouts/partials/logout' - .sticky-alerts - = render partial: 'layouts/partials/navbar' - = render partial: 'layouts/partials/sidebar' - .content-wrapper - = render partial: 'layouts/partials/alerts' - = yield :breadcrumbs - = yield - = render partial: 'layouts/partials/footer' - = yield :scripts \ No newline at end of file diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml deleted file mode 100644 index ef69772..0000000 --- a/app/views/layouts/devise.html.haml +++ /dev/null @@ -1,24 +0,0 @@ -!!! -%html - %head - = render partial: 'layouts/partials/header' - %body.dark-mode{"data-set-preferred-mode-onload": "true", - "data-dm-shortcut-enabled": "true", - "data-sidebar-shortcut-enabled": "true"} - .page-wrapper.with-navbar - = render partial: 'layouts/partials/navbar' - .content-wrapper.d-flex.align-items-center - .row - .col-sm-6.offset-sm-3 - .card.p-0 - .px-card.py-10.bg-very-dark-dm.text-center - %h2.card-title.font-size-18.m-0= yield :header - .content= yield - .px-card.py-10.bg-very-dark-dm - %p.font-size-12.text-center - This is a restricted network. Use of this network, its equipment, and resources is monitored at all - times and requires explicit permission from MythCoders, LLC. If you do not have this permission in - writing, you are violating the regulations of this network and can and will be prosecuted to the full - extent of the law. By continuing into this system, you are acknowledging that you are aware of and agree - to these terms. - = render partial: 'layouts/partials/footer' diff --git a/app/views/layouts/mailer.html.haml b/app/views/layouts/mailer.html.haml deleted file mode 100644 index b0be0fd..0000000 --- a/app/views/layouts/mailer.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! -%html - %head - %meta{'http-equiv': 'Content-Type', content: 'text/html; charset=utf-8'} - %body - = yield diff --git a/app/views/layouts/mailer.text.haml b/app/views/layouts/mailer.text.haml deleted file mode 100644 index 0a90f09..0000000 --- a/app/views/layouts/mailer.text.haml +++ /dev/null @@ -1 +0,0 @@ -= yield diff --git a/app/views/layouts/partials/_alerts.html.haml b/app/views/layouts/partials/_alerts.html.haml deleted file mode 100644 index c2621b1..0000000 --- a/app/views/layouts/partials/_alerts.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -- if flash['success'] - .alert.alert-success{role: 'alert'}= flash['success'] -- if flash['notice'] - .alert.alert-primary{role: 'alert'}= flash['notice'] -- if flash['info'] - .alert.alert-primary{role: 'alert'}= flash['info'] -- if flash['warning'] - .alert.alert-secondary{role: 'alert'}= flash['warning'] -- if flash['error'] - .alert.alert-danger{role: 'alert'}= flash['error'] \ No newline at end of file diff --git a/app/views/layouts/partials/_footer.html.haml b/app/views/layouts/partials/_footer.html.haml deleted file mode 100644 index 458413f..0000000 --- a/app/views/layouts/partials/_footer.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -%footer.pt-5.mb-3.text-muted.text-center.font-size-12 - MythCoders, LLC - %br - Made with - %i.fas.fa-heart.text-danger - in Ohio - %br - Version #{HermesApp::VERSION} \ No newline at end of file diff --git a/app/views/layouts/partials/_header.html.haml b/app/views/layouts/partials/_header.html.haml deleted file mode 100644 index 3040f6f..0000000 --- a/app/views/layouts/partials/_header.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -%meta{charset: 'utf-8'} -%title= page_title('Hermes') -%meta{name: 'viewport', content: 'width=device-width, initial-scale=1'} -%meta{name: 'author', content: 'MythCoders, LLC'} -%meta{name: 'description', content: 'Hermes'} -%meta{name: 'keywords', content: 'hermes'} -%link{rel: "shortcut icon", href: asset_path('logo.png'), type: "image/png"} - -= csrf_meta_tags -= stylesheet_link_tag 'application', 'data-turbo-track': 'reload', type: 'text/css' -= javascript_pack_tag 'main', 'data-turbo-track': 'reload', type: 'text/javascript' -%script{src: "https://kit.fontawesome.com/41aacffc34.js"} - -= yield :head diff --git a/app/views/layouts/partials/_logout.html.haml b/app/views/layouts/partials/_logout.html.haml deleted file mode 100644 index aec9889..0000000 --- a/app/views/layouts/partials/_logout.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -.modal#logout-modal{role: "dialog", tabindex: "-1"} - .modal-dialog{:role => "document"} - .modal-content - %a.close{"aria-label" => "Close", href: "#", :role => "button"} - %span{"aria-hidden" => "true"} × - %h5.modal-title Ready to Leave? - %p Any unsaved data will be lost. - - .row.mt-20 - .col - %a.btn.mr-5{"href": "#", role: "button"} Cancel - .col-auto - = form_tag destroy_user_session_path, method: :delete, "data-turbo": "false" do - %button.btn.btn-primary{type: "submit"} - %i.fas.fa-sign-out-alt - Yes, logout now diff --git a/app/views/layouts/partials/_navbar.html.haml b/app/views/layouts/partials/_navbar.html.haml deleted file mode 100644 index 48ba3a4..0000000 --- a/app/views/layouts/partials/_navbar.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -%nav.navbar - - if user_signed_in? - .navbar-content - %button.btn.btn-action{:type => "button", 'data-controller': 'sidebar', 'data-action': 'click->sidebar#toggle'} - %i.fa.fa-bars{"aria-hidden" => "true"} - %span.sr-only Toggle sidebar - %a.navbar-brand.mx-auto{href: home_path} - %img{src: asset_path('logo.png'), alt: "Hermes logo", style: "margin-right: 0.5rem"} - %span.mr-5.mr-sm-10 Hermes - - unless Rails.env.production? - %span.badge.badge-secondary.font-size-12.text-monospace.ml-auto= HermesApp.env_name diff --git a/app/views/layouts/partials/_sidebar.html.haml b/app/views/layouts/partials/_sidebar.html.haml deleted file mode 100644 index 2dc7830..0000000 --- a/app/views/layouts/partials/_sidebar.html.haml +++ /dev/null @@ -1,33 +0,0 @@ -.sidebar-overlay{'data-controller': 'sidebar', 'data-action': 'click->sidebar#toggle'} -.sidebar - .sidebar-menu - %a.sidebar-link.sidebar-link-with-icon{:href => home_path, class: home_action?('index') ? 'active': ''} - %span.sidebar-icon - %i.fas.fa-analytics{"aria-hidden" => "true"} - Dashboard - %a.sidebar-link.sidebar-link-with-icon{:href => sidekiq_web_path, target: '_blank'} - %span.sidebar-icon - %i.fas.fa-server{"aria-hidden" => "true"} - Sidekiq - .sidebar-divider - %a.sidebar-link.sidebar-link-with-icon{:href => clients_path, class: clients_controller? ? 'active' : ''} - %span.sidebar-icon - %i.fas.fa-code{"aria-hidden" => "true"} - Clients - %a.sidebar-link.sidebar-link-with-icon{:href => messages_path, class: messages_controller? ? 'active' : ''} - %span.sidebar-icon - %i.fas.fa-stream{"aria-hidden" => "true"} - Messages - %a.sidebar-link.sidebar-link-with-icon{:href => subscriptions_path, class: subscriptions_controller? ? 'active' : ''} - %span.sidebar-icon - %i.fas.fa-users{"aria-hidden" => "true"} - Subscriptions - .sidebar-divider - %a.sidebar-link.sidebar-link-with-icon{href: edit_user_registration_path} - %span.sidebar-icon - %i.fas.fa-user-circle{"aria-hidden" => "true"} - Account - %a.sidebar-link.sidebar-link-with-icon{href: "#logout-modal", role: "button"} - %span.sidebar-icon - %i.fas.fa-sign-out{"aria-hidden" => "true"} - Logout \ No newline at end of file diff --git a/app/views/mailing_topics/_form.html.haml b/app/views/mailing_topics/_form.html.haml deleted file mode 100644 index 90acf0d..0000000 --- a/app/views/mailing_topics/_form.html.haml +++ /dev/null @@ -1,16 +0,0 @@ -= f.hidden_field :id -= f.hidden_field :client_id - -.form-group - = f.label :name, class: 'col-form-label' - = f.text_field :name, class: 'form-control' -.form-group - = f.label :description, class: 'col-form-label' - = f.text_area :description, class: 'form-control' -.row - .col-12.col-md-6 - %h4.mb-4 - Options - .form-group.custom-control.custom-switch - = f.check_box :active, class: 'custom-control-input' - = f.label :active, class: 'custom-control-label' diff --git a/app/views/mailing_topics/edit.html.haml b/app/views/mailing_topics/edit.html.haml deleted file mode 100644 index 28f980a..0000000 --- a/app/views/mailing_topics/edit.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- page_title 'Edit', 'Mailing Topic' - -.content - %h1.content-title - %i.fas.fa-clipboard-list - = "Edit #{@topic.name}" - - = form_for @topic, url: client_topic_path(@topic), method: :patch do |f| - = error_messages_for 'topic' - = render partial: 'mailing_topics/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', client_path(@topic.client), class: 'btn alt-dm' - = f.submit 'Save changes', class: 'btn btn-success float-right' diff --git a/app/views/mailing_topics/new.html.haml b/app/views/mailing_topics/new.html.haml deleted file mode 100644 index 364964d..0000000 --- a/app/views/mailing_topics/new.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- page_title 'New', 'Mailing Topic' - -.content - %h1.content-title - %i.fas.fa-clipboard-list - Create new Mailing Topic for #{@topic.client.name} - - = form_for @topic, url: client_topics_path do |f| - = error_messages_for 'topic' - = render partial: 'mailing_topics/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', client_path(@topic.client), class: 'btn alt-dm' - = f.submit 'Create', class: 'btn btn-success float-right' diff --git a/app/views/messages/_activity.html.haml b/app/views/messages/_activity.html.haml deleted file mode 100644 index 91199a6..0000000 --- a/app/views/messages/_activity.html.haml +++ /dev/null @@ -1,23 +0,0 @@ -%table.table - - activity.order(:created_at).each do |r| - - color = activity_color(r.activity_type) - - message = activity_message(r.activity_type) - - %tr{class: "table-#{color}"} - %td - %h6.text-uppercase.mt-1.mb-1 - %i.fas{class: "fa-#{activity_icon(r.activity_type)}"} - = message - %p.font-size-12 - - if r.activity_type == 'received' - Hermes received the message and recorded it. - - elsif r.activity_type == 'rerouted' - Hermes modified the message and rerouted it to the Client Owner. - - elsif r.activity_type == 'held' - Hermes will deliver this when the queue is released. - - elsif r.activity_type == 'ignored' - Hermes went about its business. - - elsif r.activity_type == 'processed' - Hermes finished processing and sent it for delivery. - %small.text-muted{title: r.notification_timestamp} - #{time_ago_in_words r.notification_timestamp} ago diff --git a/app/views/messages/_header.html.haml b/app/views/messages/_header.html.haml deleted file mode 100644 index 0992a6b..0000000 --- a/app/views/messages/_header.html.haml +++ /dev/null @@ -1,22 +0,0 @@ -.content.mb-0 - .row - .col - %h1.content-title.font-size-22 - %i.fas.fa-stream - Message - %span.badge.text-monospace=@message.tracking_id - %a.btn{href: message_path(@message.tracking_id), class: ('alt-dm' if action != :summary)} - Overview - %a.btn{href: message_recipients_path(@message.tracking_id), class: ('alt-dm' if action != :recipients)} - %i.fas.fa-users - Recipients - %span.badge.badge-primary= @message.recipients.count - %a.btn{href: message_logs_path(@message.tracking_id), class: ('alt-dm' if action != :logs)} - %i.fas.fa-paperclip - Activity - %span.badge.badge-primary= @message.user_activity.count - .col-auto - .btn-group - = link_to 'All Messages', messages_path, class: 'btn alt-dm' - = link_to "#{@message.client.name} Messages", client_messages_path(@message.client_id), class: 'btn alt-dm' - = link_to 'Preview', message_preview_path(@message.tracking_id), class: 'btn btn-primary', target: '_blank' \ No newline at end of file diff --git a/app/views/messages/_overview.html.haml b/app/views/messages/_overview.html.haml deleted file mode 100644 index 156888a..0000000 --- a/app/views/messages/_overview.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -.row.mt-2 - .col-4 - .card.p-15 - .row.align-items-center - .col - %strong Client - .col-auto - %small.text-muted= link_to @message.client.name, client_path(@message.client) - %hr - .row.align-items-center - .col - %strong Environment - .col-auto - %small.text-muted= @message.environment - - .card.p-0= render partial: 'activity', locals: { activity: @message.system_activity } - .col-8 - .card - .row.align-items-center - .col - %strong From - .col-auto - %small.text-muted= @message.sender - %hr - .row.align-items-center - .col - %strong Subject - .col-auto - %small.text-muted= @message.subject - %hr - = render plain: @message.text_body, layout: false diff --git a/app/views/messages/index.html.haml b/app/views/messages/index.html.haml deleted file mode 100644 index f21b20d..0000000 --- a/app/views/messages/index.html.haml +++ /dev/null @@ -1,27 +0,0 @@ -- page_title 'Messages' - -.content - %h1.content-title.font-size-22 - %i.fas.fa-stream - Messages - -.card.p-0 - .table-responsive - %table.table.card-table - %thead - %tr - %th Date Sent - %th API Client - %th Environment - %th Subject - %tbody - - @messages.each do |c| - %tr - %td= link_to l(c.created_at), message_path(c.tracking_id) - %td= link_to c.client.name, client_path(c.client_id) - %td - %code= truncate c.environment, length: 20 - %td= truncate c.subject, length: 50 - .p-10 - = paginate @messages - = page_entries_info @messages diff --git a/app/views/messages/links.haml b/app/views/messages/links.haml deleted file mode 100644 index 029b11a..0000000 --- a/app/views/messages/links.haml +++ /dev/null @@ -1,19 +0,0 @@ -- page_title 'View Message', 'Mail Log' - -= render partial: 'header', locals: { action: :links } -.card - %table.table - %thead - %tr - %th URL - %th Timestamp - %th.float-right IP Address - %tbody - - @links.each do |r| - %tr{style: "border-bottom: none"} - %td= r.link_url - %td= r.notification_timestamp - %td.float-right= r.ip_address - %tr - %td{colspan: 3} - .text-monospace= r.user_agent diff --git a/app/views/messages/logs.haml b/app/views/messages/logs.haml deleted file mode 100644 index 0eb97a0..0000000 --- a/app/views/messages/logs.haml +++ /dev/null @@ -1,27 +0,0 @@ -- page_title 'View Message', 'Mail Log' - -= render partial: 'header', locals: { action: :logs } - -.card.p-0 - .table-responsive - %table.table - %thead - %tr - %th Event - %th Details - %th.float-right Timestamp - %tbody - - @logs.each do |r| - %tr - %td{style: "width: 8%"} - %i.fal{class: "fa-#{activity_icon(r.activity_type)}"} - = activity_message(r.activity_type) - %td - - if r.activity_type == "clicked" - = r.link_url - %hr - = r.user_agent - %td.float-right= l r.notification_timestamp - .p-10 - = paginate @logs - = page_entries_info @logs \ No newline at end of file diff --git a/app/views/messages/preview.html.haml b/app/views/messages/preview.html.haml deleted file mode 100644 index 5565272..0000000 --- a/app/views/messages/preview.html.haml +++ /dev/null @@ -1 +0,0 @@ -= @message.html_body.html_safe \ No newline at end of file diff --git a/app/views/messages/recipients.html.haml b/app/views/messages/recipients.html.haml deleted file mode 100644 index 6a1be48..0000000 --- a/app/views/messages/recipients.html.haml +++ /dev/null @@ -1,30 +0,0 @@ -- page_title 'View Message', 'Mail Log' - -= render partial: 'header', locals: { action: :recipients } -.card.p-0 - %table.table - %thead - %tr - %th{style: "width: 50%"} Recipient - %th Delivered At - %th Scheduled Send - %tbody - - @recipients.each do |r| - - has_activity = r.activities.any? - - %tr{style: ("border-bottom: none" if has_activity)} - %td{style: "width: 50%"} - = mail_to r.email - - unless r.recipient_type == "to" - %span.badge.badge-secondary.text-uppercase= r.recipient_type - %td= l(r.delivered_at) if r.delivered_at - %td= r.send_at || 'Deliver on receipt' - - if has_activity - - r.activities.each do |act| - %tr - %td{colspan: 3} - = act.reporting_mta - %code= act.smtp_response - .p-10 - = paginate @recipients - = page_entries_info @recipients diff --git a/app/views/messages/show.html.haml b/app/views/messages/show.html.haml deleted file mode 100644 index cb1d6f4..0000000 --- a/app/views/messages/show.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -- page_title 'View Message', 'Mail Log' - -= render partial: 'header', locals: { action: :summary } -= render partial: 'overview' diff --git a/app/views/subscribers/_form.html.haml b/app/views/subscribers/_form.html.haml deleted file mode 100644 index 0b7e076..0000000 --- a/app/views/subscribers/_form.html.haml +++ /dev/null @@ -1,9 +0,0 @@ -= f.hidden_field :id -= f.hidden_field :client_id - -.form-group - = f.label :name, class: 'col-form-label' - = f.text_field :name, class: 'form-control' -.form-group - = f.label :address, class: 'col-form-label' - = f.email_field :address, class: 'form-control' diff --git a/app/views/subscribers/edit.html.haml b/app/views/subscribers/edit.html.haml deleted file mode 100644 index b189038..0000000 --- a/app/views/subscribers/edit.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- page_title 'Edit', 'Subscriber' - -.content - %h1.content-title - %i.fas.fa-users - = "Edit #{@subscriber.name}" - - = form_for @subscriber, url: client_subscriber_path(@subscriber), method: :patch do |f| - = error_messages_for 'subscriber' - = render partial: 'subscribers/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', client_subscriber_path(@subscriber.client_id), class: 'btn alt-dm' - = f.submit 'Save changes', class: 'btn btn-success float-right' diff --git a/app/views/subscribers/index.html.haml b/app/views/subscribers/index.html.haml deleted file mode 100644 index d3f1faf..0000000 --- a/app/views/subscribers/index.html.haml +++ /dev/null @@ -1,39 +0,0 @@ -- page_title @client.name, 'Client' - -= render partial: 'clients/header', locals: { action: :subscribers } - -.row - .col-12.col-md-4 - = render partial: 'clients/overview' - - .col-12.col-md-8 - .card.p-0 - .px-card.py-10.bg-very-dark-dm - .row - .col - %h2.card-title.font-size-18.m-0 - %i.fas.fa-users - Subscribers - .col-auto - %a.btn.btn-sm{href: new_client_subscriber_path(@client)} - New - - if @subscribers.any? - .table-responsive - %table.table.card-table - %thead - %tr - %th Name - %th Email - %tbody - - @subscribers.each do |s| - %tr - %td= link_to s.name, client_subscriber_path(@client, s) - %td= s.address - .p-10 - = paginate @subscribers - = page_entries_info @subscribers - - else - .text-center - %h3.content-title.mt-10 No Subscribers - %p.text-muted This client does not have anyone subscribed. - diff --git a/app/views/subscribers/new.html.haml b/app/views/subscribers/new.html.haml deleted file mode 100644 index fbf450d..0000000 --- a/app/views/subscribers/new.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -- page_title 'New', 'Subscriber' - -.content - %h1.content-title - %i.fas.fa-users - Create a new Subscriber - - = form_for @subscriber, url: client_subscribers_path do |f| - = error_messages_for 'subscriber' - = render partial: 'subscribers/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', client_subscribers_path(@subscriber.client_id), class: 'btn dm-alt' - = f.submit 'Create', class: 'btn btn-success float-right' - diff --git a/app/views/subscribers/show.html.haml b/app/views/subscribers/show.html.haml deleted file mode 100644 index 4988f60..0000000 --- a/app/views/subscribers/show.html.haml +++ /dev/null @@ -1,29 +0,0 @@ -- page_title 'View', 'Subscribers' - -.content.mb-0 - .row - .col - %h1.content-title - %i.fas.fa-users - = @subscriber.name - .col-auto - = link_to 'Go Back', client_subscribers_path(@subscriber.client_id), class: 'btn alt-dm' - = link_to 'Edit', edit_client_subscriber_path(@subscriber.client_id, @subscriber), class: 'btn btn-primary' - -.card.p-0 - .px-card.py-10.bg-very-dark-dm - %h2.card-title.font-size-18.m-0 - %i.fas.fa-clipboard-list - Subscribed Mailing Topics - - if @subscriber.subscriptions.any? - .table-responsive - %table.table.card-table - %tbody - - @subscriber.subscriptions.includes(:topic).each do |s| - %tr - %td= s.topic.name - - - else - .text-center - %h3.content-title.mt-10 No Subscriptions - %p.text-muted This subscriber does not have subscriptions. \ No newline at end of file diff --git a/app/views/subscriptions/_form.html.haml b/app/views/subscriptions/_form.html.haml deleted file mode 100644 index dfcf60d..0000000 --- a/app/views/subscriptions/_form.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -= f.hidden_field :id - -.form-group - = f.label :status, class: 'col-form-label' - = f.select :status, - options_from_collection_for_select(subscription_statuses, 'value', 'label', f.object.status), - { include_blank: '- Select -' }, - { class: 'form-control' } -.form-group - = f.label :memo, class: 'col-form-label' - = f.text_area :memo, class: 'form-control' diff --git a/app/views/subscriptions/edit.html.haml b/app/views/subscriptions/edit.html.haml deleted file mode 100644 index 611f198..0000000 --- a/app/views/subscriptions/edit.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -- page_title 'All Subscriptions' - -.content - %h1.content-title - %i.fas.fa-users - Subscription - %span.badge.text-monospace=@subscription.identifier - - = form_for @subscription, url: subscription_path(@subscription), method: :patch do |f| - = error_messages_for 'subscription' - = render partial: 'subscriptions/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', subscriptions_path, class: 'btn alt-dm' - = f.submit 'Save changes', class: 'btn btn-success float-right' \ No newline at end of file diff --git a/app/views/subscriptions/index.html.haml b/app/views/subscriptions/index.html.haml deleted file mode 100644 index 33ba7c6..0000000 --- a/app/views/subscriptions/index.html.haml +++ /dev/null @@ -1,26 +0,0 @@ -- page_title 'All Subscriptions' - -.content - %h1.content-title.font-size-22 - %i.fas.fa-users - All Subscriptions - -.card.p-0 - .table-responsive - %table.table.card-table - %thead - %tr - %th User - %th Client - %th Topic - %th Status - %tbody - - @subscriptions.each do |s| - %tr - %td= link_to s.subscriber.name, edit_subscription_path(s) - %td= s.topic.client.name - %td= s.topic.name - %td= l(s.created_at) - .p-10 - = paginate @subscriptions - = page_entries_info @subscriptions diff --git a/app/views/templates/_form.html.haml b/app/views/templates/_form.html.haml deleted file mode 100644 index 03e6e08..0000000 --- a/app/views/templates/_form.html.haml +++ /dev/null @@ -1,30 +0,0 @@ -= f.hidden_field :id -= f.hidden_field :client_id - -.form-group - = f.label :name, class: 'col-form-label' - = f.text_field :name, class: 'form-control' -.form-row - .form-group.col-12.col-lg-6 - = f.label :sender_name, class: 'col-form-label' - = f.text_field :sender_name, class: 'form-control' - .form-group.col-12.col-lg-6 - = f.label :sender_address, class: 'col-form-label' - = f.email_field :sender_address, class: 'form-control' -.form-group - = f.label :html_body, class: 'col-form-label' - = f.text_area :html_body, class: 'form-control' -.form-group - = f.label :text_body, class: 'col-form-label' - = f.text_area :text_body, class: 'form-control' -.form-group - = f.label :json_layout, class: 'col-form-label' - = f.text_area :json_layout, class: 'form-control' -%hr.mt-5.mb-5 -.row - .col-12.col-md-6 - %h4.mb-4 - Options - .form-group.custom-control.custom-switch - = f.check_box :active, class: 'custom-control-input' - = f.label :active, class: 'custom-control-label' diff --git a/app/views/templates/edit.html.haml b/app/views/templates/edit.html.haml deleted file mode 100644 index 85b2ed3..0000000 --- a/app/views/templates/edit.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- page_title 'Edit', 'Template' - -.content - %h1.content-title - %i.fas.fa-object-group - = "Edit #{@template.name}" - - = form_for @template, url: client_template_path(@template), method: :patch do |f| - = error_messages_for 'template' - = render partial: 'templates/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', client_path(@template.client), class: 'btn alt-dm' - = f.submit 'Save changes', class: 'btn btn-success float-right' diff --git a/app/views/templates/new.html.haml b/app/views/templates/new.html.haml deleted file mode 100644 index 480059a..0000000 --- a/app/views/templates/new.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -- page_title 'New', 'Template' - -.content - %h1.content-title - %i.fas.fa-object-group - Create a new Template - - = form_for @template, url: client_templates_path do |f| - = error_messages_for 'template' - = render partial: 'templates/form', locals: { f: f } - %hr.mt-5.mb-5 - = link_to 'Cancel', client_path(@template.client_id), class: 'btn alt-dm' - = f.submit 'Create', class: 'btn btn-success float-right' diff --git a/app/views/templates/show.html.haml b/app/views/templates/show.html.haml deleted file mode 100644 index 5ae9ded..0000000 --- a/app/views/templates/show.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -- page_title 'New', 'Template' - -.header - .header-body - .row.align-items-center - .col - %h6.header-pretitle - Template - %h1.card-title - %i.fas.fa-clipboard-list - = @template.name - .col-auto - = link_to 'Go Back', client_path(@template.client_id), class: 'btn alt-dm' - = link_to 'Edit', edit_client_template_path(@template), class: 'btn btn-primary' - -.embed-responsive.embed-responsive-1by1 - %iframe.embed-responsive-item{srcdoc: @template.html_body, name: 'email-preview', allowfullscreen: 'true'} \ No newline at end of file diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index 4df1949..0000000 --- a/babel.config.js +++ /dev/null @@ -1,70 +0,0 @@ -module.exports = function(api) { - var validEnv = ['development', 'test', 'production'] - var currentEnv = api.env() - var isDevelopmentEnv = api.env('development') - var isProductionEnv = api.env('production') - var isTestEnv = api.env('test') - - if (!validEnv.includes(currentEnv)) { - throw new Error( - 'Please specify a valid `NODE_ENV` or ' + - '`BABEL_ENV` environment variables. Valid values are "development", ' + - '"test", and "production". Instead, received: ' + - JSON.stringify(currentEnv) + - '.' - ) - } - - return { - presets: [ - isTestEnv && [ - '@babel/preset-env', - { - targets: { - node: 'current' - } - } - ], - (isProductionEnv || isDevelopmentEnv) && [ - '@babel/preset-env', - { - forceAllTransforms: true, - useBuiltIns: 'entry', - corejs: 3, - modules: false, - exclude: ['transform-typeof-symbol'] - } - ] - ].filter(Boolean), - plugins: [ - 'babel-plugin-macros', - '@babel/plugin-syntax-dynamic-import', - isTestEnv && 'babel-plugin-dynamic-import-node', - '@babel/plugin-transform-destructuring', - [ - '@babel/plugin-proposal-class-properties', - { - loose: true - } - ], - [ - '@babel/plugin-proposal-object-rest-spread', - { - useBuiltIns: true - } - ], - [ - '@babel/plugin-transform-runtime', - { - helpers: false - } - ], - [ - '@babel/plugin-transform-regenerator', - { - async: false - } - ] - ].filter(Boolean) - } -} diff --git a/bin/bundle b/bin/bundle deleted file mode 100755 index f19acf5..0000000 --- a/bin/bundle +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails deleted file mode 100755 index 0739660..0000000 --- a/bin/rails +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env ruby -APP_PATH = File.expand_path('../config/application', __dir__) -require_relative '../config/boot' -require 'rails/commands' diff --git a/bin/rake b/bin/rake deleted file mode 100755 index 1724048..0000000 --- a/bin/rake +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env ruby -require_relative '../config/boot' -require 'rake' -Rake.application.run diff --git a/bin/setup b/bin/setup deleted file mode 100755 index 5853b5e..0000000 --- a/bin/setup +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env ruby -require 'fileutils' - -# path to your application root. -APP_ROOT = File.expand_path('..', __dir__) - -def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") -end - -FileUtils.chdir APP_ROOT do - # This script is a way to setup or update your development environment automatically. - # This script is idempotent, so that you can run it at anytime and get an expectable outcome. - # Add necessary setup steps to this file. - - puts '== Installing dependencies ==' - system! 'gem install bundler --conservative' - system('bundle check') || system!('bundle install') - - # Install JavaScript dependencies - # system('bin/yarn') - - # puts "\n== Copying sample files ==" - # unless File.exist?('config/database.yml') - # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' - # end - - puts "\n== Preparing database ==" - system! 'bin/rails db:prepare' - - puts "\n== Removing old logs and tempfiles ==" - system! 'bin/rails log:clear tmp:clear' - - puts "\n== Restarting application server ==" - system! 'bin/rails restart' -end diff --git a/bin/spring b/bin/spring deleted file mode 100755 index fb2ec2e..0000000 --- a/bin/spring +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env ruby - -# This file loads spring without using Bundler, in order to be fast. -# It gets overwritten when you run the `spring binstub` command. - -unless defined?(Spring) - require 'rubygems' - require 'bundler' - - lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) - spring = lockfile.specs.detect { |spec| spec.name == "spring" } - if spring - Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path - gem 'spring', spring.version - require 'spring/binstub' - end -end diff --git a/bin/update b/bin/update deleted file mode 100755 index 58bfaed..0000000 --- a/bin/update +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env ruby -require 'fileutils' -include FileUtils - -# path to your application root. -APP_ROOT = File.expand_path('..', __dir__) - -def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") -end - -chdir APP_ROOT do - # This script is a way to update your development environment automatically. - # Add necessary update steps to this file. - - puts '== Installing dependencies ==' - system! 'gem install bundler --conservative' - system('bundle check') || system!('bundle install') - - # Install JavaScript dependencies if using Yarn - # system('bin/yarn') - - puts "\n== Updating database ==" - system! 'bin/rails db:migrate' - - puts "\n== Removing old logs and tempfiles ==" - system! 'bin/rails log:clear tmp:clear' - - puts "\n== Restarting application server ==" - system! 'bin/rails restart' -end diff --git a/bin/webpack b/bin/webpack deleted file mode 100755 index 1031168..0000000 --- a/bin/webpack +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env ruby - -ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" -ENV["NODE_ENV"] ||= "development" - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "bundler/setup" - -require "webpacker" -require "webpacker/webpack_runner" - -APP_ROOT = File.expand_path("..", __dir__) -Dir.chdir(APP_ROOT) do - Webpacker::WebpackRunner.run(ARGV) -end diff --git a/bin/webpack-dev-server b/bin/webpack-dev-server deleted file mode 100755 index dd96627..0000000 --- a/bin/webpack-dev-server +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env ruby - -ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" -ENV["NODE_ENV"] ||= "development" - -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) - -require "bundler/setup" - -require "webpacker" -require "webpacker/dev_server_runner" - -APP_ROOT = File.expand_path("..", __dir__) -Dir.chdir(APP_ROOT) do - Webpacker::DevServerRunner.run(ARGV) -end diff --git a/bin/yarn b/bin/yarn deleted file mode 100755 index 460dd56..0000000 --- a/bin/yarn +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env ruby -APP_ROOT = File.expand_path('..', __dir__) -Dir.chdir(APP_ROOT) do - begin - exec "yarnpkg", *ARGV - rescue Errno::ENOENT - $stderr.puts "Yarn executable was not detected in the system." - $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" - exit 1 - end -end diff --git a/config.ru b/config.ru deleted file mode 100644 index bff88d6..0000000 --- a/config.ru +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -# This file is used by Rack-based servers to start the application. - -require_relative "config/environment" - -run Rails.application diff --git a/config/application.rb b/config/application.rb deleted file mode 100644 index 2b1562b..0000000 --- a/config/application.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: true - -require_relative "boot" - -require "active_record/railtie" -require "active_storage/engine" -require "action_controller/railtie" -require "action_view/railtie" -require "action_mailer/railtie" -require "active_job/railtie" -require "action_cable/engine" -# require 'action_mailbox/engine' -require "action_text/engine" -# require 'rails/test_unit/railtie' -require "sprockets/railtie" -require "view_component/engine" - -require "pinglish" - -# Require the gems listed in Gemfile, including any gems -# you've limited to :test, :development, or :production. -Bundler.require(*Rails.groups) - -module Hermes - class Application < Rails::Application - # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 5.2 - - config.encoding = "utf-8" - config.time_zone = "Eastern Time (US & Canada)" - config.beginning_of_week = :sunday - config.public_file_server.enabled - config.autoload_paths += %W[#{config.root}/lib] - # config.require_master_key = true - - config.active_job.queue_adapter = :sidekiq - - # Storage - config.active_storage.variant_processor = :vips - config.active_storage.routes_prefix = "/storage" - - # Logging - config.lograge.enabled = true - end -end diff --git a/config/boot.rb b/config/boot.rb deleted file mode 100644 index aef6d03..0000000 --- a/config/boot.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) - -require "bundler/setup" # Set up gems listed in the Gemfile. -require "bootsnap/setup" # Speed up boot time by caching expensive operations. diff --git a/config/cable.yml b/config/cable.yml deleted file mode 100644 index 3148f58..0000000 --- a/config/cable.yml +++ /dev/null @@ -1,10 +0,0 @@ -development: - adapter: async - -test: - adapter: test - -production: - adapter: redis - url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> - channel_prefix: hermes_production diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc deleted file mode 100644 index 4b616f8..0000000 --- a/config/credentials.yml.enc +++ /dev/null @@ -1 +0,0 @@ -KojZTkTApZ6K2QbJZRXhy/Kn4iiVlGoXMFfoifcV3jGudIw6wWQMcbtI7UdTBVLDifrdccsT0AIhB8jTpR/3j0vEwpUYYHtJzGojeiaATgyOQ4skTqFEKTsLcHE2EvamzCW/nrWNdy11Y6S7i905hCYVkYHbMeaTI8m24DRl6Jbl0pvobXUDcjIlX7t9qKvbIz8MPq9zNvIVLU5cT0mxmoaUBhc62DnQNsxwffPbrnGqzNOGp+/O+lOw57j4lRGKSF/aGsHpFW5tnl6fzTD/2Zs4ND955UEpFbJy9hbBTKtzcuq29GB+9SJEWPhMY6aT/nyYDVWOVwABGeYC0P8+2bjWSm+xKjJKpN+qmqsl7cohcwYQnPJnqveTRdjCObbuxG7tjJ8Ey0n5owX9gQjOBgopdWqRtcwbrIxJbh8bZS5/pr3qug9hjHWMEZki89f+RV9Iw8BQ0rECP45H7G7MflzsJIyqTm/Ygau8/U40LL1jKxFjlD07W7IsswyQjVhfoi1mpBHVpT7YxBYg01Psksw826CATDTrYLYkGgnr4/S3Xvvpivk9nNbMHR3to7x9OjPxmsHjjs2C5AO8Vc+ey96+Ir+lzyMI3qtRSK/94N2KMkH+ci45MuhrcNsKUlmSOcdE5zyLE+I1GxQgBnp7Oi/lnz7CAcXEOiTjSCVBfRZpt5vZWxsF2CpbEmrxZYLZq8X/kO9179AYUK8mV9ZPhcY1JgnW4fBZAAsyx8Acl0iEg+jJ0Odqq/2a6dm2dcvqn3k5iJ4ycoKV4opxQNI7p+xdoemvL+HkWs8NAvMUBbNW7WpeF97QNDUAHiTERqV0c6L82+65d8pO2tqP65W0Churlxh4RhPj3YczRAdgqZ38nPMqXHeUUlt22lltHLfbNh8p4aLSR0nDsBBrKw==--/xgwOug7YRh0Z3CT--ch0M3XQV7v5KIuRuM2OtCQ== \ No newline at end of file diff --git a/config/database.yml b/config/database.yml deleted file mode 100644 index 99babb8..0000000 --- a/config/database.yml +++ /dev/null @@ -1,30 +0,0 @@ -default: &default - adapter: postgresql - pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> - timeout: 7500 - host: myth-psql - port: 5432 - username: postgres - password: postgres - -development: - <<: *default - database: hermes_dev - -test: - <<: *default - database: hermes_test - -review: - <<: *default - url: <%= ENV['DATABASE_URL'] %> - -production: - <<: *default - url: <%= ENV['DATABASE_URL'] %> - prepared_statements: false - advisory_locks: false - connect_timeout: 5 - checkout_timeout: 5 - variables: - statement_timeout: 30000 # 30 seconds diff --git a/config/deploy/prod.nomad b/config/deploy/prod.nomad deleted file mode 100644 index acc4927..0000000 --- a/config/deploy/prod.nomad +++ /dev/null @@ -1,171 +0,0 @@ -job "hermes" { - datacenters = ["mcdig"] - - meta { - version = "2203" - } - - update { - max_parallel = 1 - health_check = "checks" - min_healthy_time = "20s" - healthy_deadline = "3m" - progress_deadline = "10m" - auto_revert = true - auto_promote = true - canary = 2 - stagger = "30s" - } - - group "app" { - count = 2 - - constraint { - attribute = "${node.class}" - operator = "=" - value = "app" - } - - network { - mode = "bridge" - port "puma" { - to = 5000 - } - } - - service { - name = "hermes-rails" - port = "puma" - - tags = [ - "traefik.enable=true", - "traefik.http.routers.hermes.rule=Host(`hermes.mythcoders.net`)", - "traefik.http.routers.hermes.tls=true", - "traefik.http.routers.hermes.tls.certresolver=letsEncrypt", - ] - - connect { - sidecar_service { - proxy { - local_service_address = "0.0.0.0" - local_service_port = 5000 - } - } - } - - check { - name = "heartbeat" - type = "http" - path = "/_heartbeat" - interval = "10s" - timeout = "3s" - } - } - - task "rails" { - driver = "docker" - - config { - image = "ghcr.io/mythcoders/hermes:latest" - ports = ["puma"] - } - - template { - data = < "public, max-age=#{2.days.to_i}" - } - else - config.action_controller.perform_caching = false - config.cache_store = :null_store - end - - config.action_mailer.preview_path = "#{Rails.root}/spec/mailer_previews" - config.action_mailer.delivery_method = :smtp - config.action_mailer.perform_deliveries = true - config.action_mailer.raise_delivery_errors = true - config.action_mailer.perform_caching = false - config.action_mailer.default_url_options = { - host: ENV["ENVIRONMENT_URL"] - } - config.action_mailer.smtp_settings = { - user_name: Rails.application.credentials.dig(:email, :username), - password: Rails.application.credentials.dig(:email, :password), - domain: "mythcoders.com", - address: "email-smtp.us-east-1.amazonaws.com", - port: 587, - authentication: :plain, - enable_starttls_auto: true - } - - config.active_support.deprecation = :log - config.active_storage.service = :local - # config.active_storage.service = :amazon - config.active_record.migration_error = :page_load - config.assets.debug = false - config.assets.quiet = true - config.file_watcher = ActiveSupport::EventedFileUpdateChecker -end diff --git a/config/environments/production.rb b/config/environments/production.rb deleted file mode 100644 index 5f720fa..0000000 --- a/config/environments/production.rb +++ /dev/null @@ -1,53 +0,0 @@ -# frozen_string_literal: true - -Rails.application.configure do - config.eager_load = true - config.consider_all_requests_local = false - config.action_controller.perform_caching = true - - if ENV["CDN_URL"] - config.action_controller.asset_host = ENV["CDN_URL"] - config.action_mailer.asset_host = ENV["CDN_URL"] - else - config.action_mailer.asset_host = "https://#{ENV["ENVIRONMENT_URL"]}" - end - - config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? - - config.assets.js_compressor = Uglifier.new(harmony: true) - config.assets.css_compressor = :sass - - config.log_level = :info - config.log_tags = [:request_id] - - config.active_storage.service = :amazon - - config.i18n.fallbacks = true - config.active_support.deprecation = :notify - config.log_formatter = ::Logger::Formatter.new - - if ENV["RAILS_LOG_TO_STDOUT"].present? - logger = ActiveSupport::Logger.new($stdout) - logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) - end - - config.active_record.dump_schema_after_migration = false - - config.action_mailer.delivery_method = :smtp - config.action_mailer.perform_deliveries = true - config.action_mailer.raise_delivery_errors = true - config.action_mailer.perform_caching = false - config.action_mailer.default_url_options = { - host: ENV["ENVIRONMENT_URL"] - } - config.action_mailer.smtp_settings = { - user_name: Rails.application.credentials.dig(:email, :username), - password: Rails.application.credentials.dig(:email, :password), - domain: "mythcoders.com", - address: "email-smtp.us-east-1.amazonaws.com", - port: 587, - authentication: :plain, - enable_starttls_auto: true - } -end diff --git a/config/environments/review.rb b/config/environments/review.rb deleted file mode 100644 index 63755fc..0000000 --- a/config/environments/review.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require Rails.root.join("config", "environments", "production") - -Rails.application.configure do - config.log_level = :debug -end diff --git a/config/environments/staging.rb b/config/environments/staging.rb deleted file mode 100644 index 096a201..0000000 --- a/config/environments/staging.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true - -require Rails.root.join("config", "environments", "production") diff --git a/config/environments/test.rb b/config/environments/test.rb deleted file mode 100644 index 88aaa7a..0000000 --- a/config/environments/test.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -Rails.application.configure do - config.cache_classes = true - config.eager_load = false - - config.log_level = :info - - config.public_file_server.enabled = true - config.public_file_server.headers = { - 'Cache-Control': "public, max-age=#{1.hour.to_i}" - } - - config.assets.compile = true - config.assets.prefix = "assets_test" - config.action_controller.asset_host = "file://#{::Rails.root}/public" - config.serve_static_assets = true - config.assets.js_compressor = Uglifier.new(harmony: true) - config.assets.css_compressor = :sass - - config.consider_all_requests_local = true - config.action_controller.perform_caching = false - config.require_master_key = true - config.action_dispatch.show_exceptions = false - - config.action_controller.allow_forgery_protection = false - - config.action_mailer.perform_deliveries = false - config.action_mailer.default_url_options = { - host: "http://hermes.localhost" - } - - config.active_support.deprecation = :stderr -end diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb deleted file mode 100644 index 6d56e43..0000000 --- a/config/initializers/application_controller_renderer.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -# Be sure to restart your server when you modify this file. - -# ActiveSupport::Reloader.to_prepare do -# ApplicationController.renderer.defaults.merge!( -# http_host: 'example.org', -# https: false -# ) -# end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb deleted file mode 100644 index 8f7f351..0000000 --- a/config/initializers/assets.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -# Be sure to restart your server when you modify this file. - -# Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = "1.0" - -# Add additional assets to the asset load path. -Rails.application.config.assets.paths << Rails.root.join("vendor", "stylesheets") -# Add Yarn node_modules folder to the asset load path. -Rails.application.config.assets.paths << Rails.root.join("node_modules") - -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in the app/assets -# folder are already added. -Rails.application.config.assets.precompile += %w[application.css] diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb deleted file mode 100644 index 4b63f28..0000000 --- a/config/initializers/backtrace_silencers.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -# Be sure to restart your server when you modify this file. - -# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. -# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } - -# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. -# Rails.backtrace_cleaner.remove_silencers! diff --git a/config/initializers/bootstrap_html_errors.rb b/config/initializers/bootstrap_html_errors.rb deleted file mode 100644 index 8413f57..0000000 --- a/config/initializers/bootstrap_html_errors.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -# https://gist.github.com/telwell/db42a4dafbe9cc3b7988debe358c88ad -ActionView::Base.field_error_proc = proc do |html_tag, instance| - html = "" - form_fields = %w[ - textarea - input - select - ] - - elements = Nokogiri::HTML::DocumentFragment.parse(html_tag).css "label, #{form_fields.join(", ")}" - elements.each do |e| - if e.node_name.eql? "label" - html = e.to_s.html_safe - elsif form_fields.include? e.node_name - e["class"] += " is-invalid" - html = if instance.error_message.is_a?(Array) || instance.error_message.is_a?(ActiveModel::DeprecationHandlingMessageArray) - %(#{e}
#{instance.error_message.uniq.join(", ")}
).html_safe - else - %(#{e}
#{instance.error_message}
).html_safe - end - end - end - html -end diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb deleted file mode 100644 index f3bcce5..0000000 --- a/config/initializers/content_security_policy.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true -# Be sure to restart your server when you modify this file. - -# Define an application-wide content security policy -# For further information see the following documentation -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy - -# Rails.application.config.content_security_policy do |policy| -# policy.default_src :self, :https -# policy.font_src :self, :https, :data -# policy.img_src :self, :https, :data -# policy.object_src :none -# policy.script_src :self, :https -# policy.style_src :self, :https -# # If you are using webpack-dev-server then specify webpack-dev-server host -# policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development? - -# # Specify URI for violation reports -# # policy.report_uri "/csp-violation-report-endpoint" -# end - -# If you are using UJS then enable automatic nonce generation -# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } - -# Set the nonce only to specific directives -# Rails.application.config.content_security_policy_nonce_directives = %w(script-src) - -# Report CSP violations to a specified URI -# For further information see the following documentation: -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only -# Rails.application.config.content_security_policy_report_only = true diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb deleted file mode 100644 index ee8dff9..0000000 --- a/config/initializers/cookies_serializer.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -# Be sure to restart your server when you modify this file. - -# Specify a serializer for the signed and encrypted cookie jars. -# Valid options are :json, :marshal, and :hybrid. -Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb deleted file mode 100644 index 6ac1c16..0000000 --- a/config/initializers/devise.rb +++ /dev/null @@ -1,290 +0,0 @@ -# frozen_string_literal: true - -# Use this hook to configure devise mailer, warden hooks and so forth. -# Many of these configuration options can be set straight in your model. -Devise.setup do |config| - # The secret key used by Devise. Devise uses this key to generate - # random tokens. Changing this key will render invalid all existing - # confirmation, reset password and unlock tokens in the database. - # Devise will use the `secret_key_base` as its `secret_key` - # by default. You can change it below and use your own secret key. - # config.secret_key = '676a1f439509d9852ce459566e8341815d01c76165360d6eda4f69856a9377005f23d236cc844132afef6d1994ff4c7891b4d30d34f75aa45161ef4149002cd9' - - # ==> Controller configuration - # Configure the parent class to the devise controllers. - config.parent_controller = "TurboController" - - # ==> Mailer Configuration - # Configure the e-mail address which will be shown in Devise::Mailer, - # note that it will be overwritten if you use your own mailer class - # with default "from" parameter. - config.mailer_sender = "support@mythcoders.com" - - # Configure the class responsible to send e-mails. - # config.mailer = 'Devise::Mailer' - - # Configure the parent class responsible to send e-mails. - # config.parent_mailer = 'ActionMailer::Base' - - # ==> ORM configuration - # Load and configure the ORM. Supports :active_record (default) and - # :mongoid (bson_ext recommended) by default. Other ORMs may be - # available as additional gems. - require "devise/orm/active_record" - - # ==> Configuration for any authentication mechanism - # Configure which keys are used when authenticating a user. The default is - # just :email. You can configure it to use [:username, :subdomain], so for - # authenticating a user, both parameters are required. Remember that those - # parameters are used only when authenticating and not when retrieving from - # session. If you need permissions, you should implement that in a before filter. - # You can also supply a hash where the value is a boolean determining whether - # or not authentication should be aborted when the value is not present. - # config.authentication_keys = [:email] - - # Configure parameters from the request object used for authentication. Each entry - # given should be a request method and it will automatically be passed to the - # find_for_authentication method and considered in your model lookup. For instance, - # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. - # The same considerations mentioned for authentication_keys also apply to request_keys. - # config.request_keys = [] - - # Configure which authentication keys should be case-insensitive. - # These keys will be downcased upon creating or modifying a user and when used - # to authenticate or find a user. Default is :email. - config.case_insensitive_keys = [:email] - - # Configure which authentication keys should have whitespace stripped. - # These keys will have whitespace before and after removed upon creating or - # modifying a user and when used to authenticate or find a user. Default is :email. - config.strip_whitespace_keys = [:email] - - # Tell if authentication through request.params is enabled. True by default. - # It can be set to an array that will enable params authentication only for the - # given strategies, for example, `config.params_authenticatable = [:database]` will - # enable it only for database (email + password) authentication. - # config.params_authenticatable = true - - # Tell if authentication through HTTP Auth is enabled. False by default. - # It can be set to an array that will enable http authentication only for the - # given strategies, for example, `config.http_authenticatable = [:database]` will - # enable it only for database authentication. The supported strategies are: - # :database = Support basic authentication with authentication key + password - # config.http_authenticatable = false - - # If 401 status code should be returned for AJAX requests. True by default. - # config.http_authenticatable_on_xhr = true - - # The realm used in Http Basic Authentication. 'Application' by default. - # config.http_authentication_realm = 'Application' - - # It will change confirmation, password recovery and other workflows - # to behave the same regardless if the e-mail provided was right or wrong. - # Does not affect registerable. - # config.paranoid = true - - # By default Devise will store the user in session. You can skip storage for - # particular strategies by setting this option. - # Notice that if you are skipping storage for all authentication paths, you - # may want to disable generating routes to Devise's sessions controller by - # passing skip: :sessions to `devise_for` in your config/routes.rb - config.skip_session_storage = [:http_auth] - - # By default, Devise cleans up the CSRF token on authentication to - # avoid CSRF token fixation attacks. This means that, when using AJAX - # requests for sign in and sign up, you need to get a new CSRF token - # from the server. You can disable this option at your own risk. - # config.clean_up_csrf_token_on_authentication = true - - # When false, Devise will not attempt to reload routes on eager load. - # This can reduce the time taken to boot the app but if your application - # requires the Devise mappings to be loaded during boot time the application - # won't boot properly. - # config.reload_routes = true - - # ==> Configuration for :database_authenticatable - # For bcrypt, this is the cost for hashing the password and defaults to 11. If - # using other algorithms, it sets how many times you want the password to be hashed. - # - # Limiting the stretches to just one in testing will increase the performance of - # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use - # a value less than 10 in other environments. Note that, for bcrypt (the default - # algorithm), the cost increases exponentially with the number of stretches (e.g. - # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). - config.stretches = Rails.env.test? ? 1 : 11 - - # Set up a pepper to generate the hashed password. - # config.pepper = '3b3f260ff9fa5c6f663805c4091035c7c04016b54afe34c795b1b432043a39f7e898a1d3fb79be707e71aac09b6dd05e81f3647700cf109c533e99ffe273cb2c' - - # Send a notification to the original email when the user's email is changed. - # config.send_email_changed_notification = false - - # Send a notification email when the user's password is changed. - # config.send_password_change_notification = false - - # ==> Configuration for :confirmable - # A period that the user is allowed to access the website even without - # confirming their account. For instance, if set to 2.days, the user will be - # able to access the website for two days without confirming their account, - # access will be blocked just in the third day. Default is 0.days, meaning - # the user cannot access the website without confirming their account. - # config.allow_unconfirmed_access_for = 2.days - - # A period that the user is allowed to confirm their account before their - # token becomes invalid. For example, if set to 3.days, the user can confirm - # their account within 3 days after the mail was sent, but on the fourth day - # their account can't be confirmed with the token any more. - # Default is nil, meaning there is no restriction on how long a user can take - # before confirming their account. - # config.confirm_within = 3.days - - # If true, requires any email changes to be confirmed (exactly the same way as - # initial account confirmation) to be applied. Requires additional unconfirmed_email - # db field (see migrations). Until confirmed, new email is stored in - # unconfirmed_email column, and copied to email column on successful confirmation. - config.reconfirmable = true - - # Defines which key will be used when confirming an account - # config.confirmation_keys = [:email] - - # ==> Configuration for :rememberable - # The time the user will be remembered without asking for credentials again. - # config.remember_for = 2.weeks - - # Invalidates all the remember me tokens when the user signs out. - config.expire_all_remember_me_on_sign_out = true - - # If true, extends the user's remember period when remembered via cookie. - # config.extend_remember_period = false - - # Options to be passed to the created cookie. For instance, you can set - # secure: true in order to force SSL only cookies. - # config.rememberable_options = {} - - # ==> Configuration for :validatable - # Range for password length. - config.password_length = 12..128 - - # Email regex used to validate email formats. It simply asserts that - # one (and only one) @ exists in the given string. This is mainly - # to give user feedback and not to assert the e-mail validity. - config.email_regexp = /\A[^@\s]+@[^@\s]+\z/ - - # ==> Configuration for :timeoutable - # The time you want to timeout the user session without activity. After this - # time the user will be asked for credentials again. Default is 30 minutes. - config.timeout_in = Rails.env.development? ? 1.week : 2.hours - - # ==> Configuration for :lockable - # Defines which strategy will be used to lock an account. - # :failed_attempts = Locks an account after a number of failed attempts to sign in. - # :none = No lock strategy. You should handle locking by yourself. - # config.lock_strategy = :failed_attempts - - # Defines which key will be used when locking and unlocking an account - # config.unlock_keys = [:email] - - # Defines which strategy will be used to unlock an account. - # :email = Sends an unlock link to the user email - # :time = Re-enables login after a certain amount of time (see :unlock_in below) - # :both = Enables both strategies - # :none = No unlock strategy. You should handle unlocking by yourself. - # config.unlock_strategy = :both - - # Number of authentication tries before locking an account if lock_strategy - # is failed attempts. - # config.maximum_attempts = 20 - - # Time interval to unlock the account if :time is enabled as unlock_strategy. - # config.unlock_in = 1.hour - - # Warn on the last attempt before the account is locked. - # config.last_attempt_warning = true - - # ==> Configuration for :recoverable - # - # Defines which key will be used when recovering the password for an account - # config.reset_password_keys = [:email] - - # Time interval you can reset your password with a reset password key. - # Don't put a too small interval or your users won't have the time to - # change their passwords. - config.reset_password_within = 6.hours - - # When set to false, does not sign a user in automatically after their password is - # reset. Defaults to true, so a user is signed in automatically after a reset. - # config.sign_in_after_reset_password = true - - # ==> Configuration for :encryptable - # Allow you to use another hashing or encryption algorithm besides bcrypt (default). - # You can use :sha1, :sha512 or algorithms from others authentication tools as - # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20 - # for default behavior) and :restful_authentication_sha1 (then you should set - # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper). - # - # Require the `devise-encryptable` gem when using anything other than bcrypt - # config.encryptor = :sha512 - - # ==> Scopes configuration - # Turn scoped views on. Before rendering "sessions/new", it will first check for - # "users/sessions/new". It's turned off by default because it's slower if you - # are using only default views. - # config.scoped_views = false - - # Configure the default scope given to Warden. By default it's the first - # devise role declared in your routes (usually :user). - # config.default_scope = :user - - # Set this configuration to false if you want /users/sign_out to sign out - # only the current scope. By default, Devise signs out all scopes. - # config.sign_out_all_scopes = true - - # ==> Navigation configuration - # Lists the formats that should be treated as navigational. Formats like - # :html, should redirect to the sign in page when the user does not have - # access, but formats like :xml or :json, should return 401. - # - # If you have any extra navigational formats, like :iphone or :mobile, you - # should add them to the navigational formats lists. - # - # The "*/*" below is required to match Internet Explorer requests. - # config.navigational_formats = ['*/*', :html] - - # The default HTTP method used to sign out a resource. Default is :delete. - config.sign_out_via = :delete - - # ==> OmniAuth - # Add a new OmniAuth provider. Check the wiki for more information on setting - # up on your models and hooks. - # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' - - # ==> Warden configuration - # If you want to use other strategies, that are not supported by Devise, or - # change the failure app, you can configure them inside the config.warden block. - # - # config.warden do |manager| - # manager.intercept_401 = false - # manager.default_strategies(scope: :user).unshift :some_external_strategy - # end - - # ==> Mountable engine configurations - # When using Devise inside an engine, let's call it `MyEngine`, and this engine - # is mountable, there are some extra configurations to be taken into account. - # The following options are available, assuming the engine is mounted as: - # - # mount MyEngine, at: '/my_engine' - # - # The router that invoked `devise_for`, in the example above, would be: - # config.router_name = :my_engine - # - # When using OmniAuth, Devise cannot automatically set OmniAuth path, - # so you need to do it manually. For the users scope, it would be: - # config.omniauth_path_prefix = '/my_engine/users/auth' - - # ==> Turbolinks configuration - # If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly: - # - # ActiveSupport.on_load(:devise_failure_app) do - # include Turbolinks::Controller - # end -end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb deleted file mode 100644 index 7a4f47b..0000000 --- a/config/initializers/filter_parameter_logging.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -# Be sure to restart your server when you modify this file. - -# Configure sensitive parameters which will be filtered from the log file. -Rails.application.config.filter_parameters += [:password] diff --git a/config/initializers/hermes.rb b/config/initializers/hermes.rb deleted file mode 100644 index c571616..0000000 --- a/config/initializers/hermes.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true - -# ActionMailer::Base.add_delivery_method :hermes, Hermes::Mailbox, environment: Rails.env diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb deleted file mode 100644 index dc84742..0000000 --- a/config/initializers/inflections.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -# Be sure to restart your server when you modify this file. - -# Add new inflection rules using the following format. Inflections -# are locale specific, and you may define rules for as many different -# locales as you wish. All of these examples are active by default: -# ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' -# inflect.uncountable %w( fish sheep ) -# end - -# These inflection rules are supported but not enabled by default: -# ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.acronym 'RESTful' -# end diff --git a/config/initializers/kaminari.rb b/config/initializers/kaminari.rb deleted file mode 100644 index c15f423..0000000 --- a/config/initializers/kaminari.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -Kaminari.configure do |config| - config.default_per_page = 15 - config.max_per_page = 50 - # config.window = 4 - # config.outer_window = 0 - # config.left = 0 - # config.right = 0 - # config.page_method_name = :page - # config.param_name = :page -end diff --git a/config/initializers/lograge.rb b/config/initializers/lograge.rb deleted file mode 100644 index cc42f45..0000000 --- a/config/initializers/lograge.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -Rails.application.configure do - config.lograge.enabled = true - - config.lograge.custom_payload do |controller| - { - host: controller.request.host, - user_id: controller.current_user.try(:id) - } - end - - config.lograge.custom_options = lambda do |event| - exceptions = %w[controller action format id] - { - params: event.payload[:params].except(*exceptions) - } - end -end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb deleted file mode 100644 index be6fedc..0000000 --- a/config/initializers/mime_types.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -# Be sure to restart your server when you modify this file. - -# Add new mime types for use in respond_to blocks: -# Mime::Type.register "text/richtext", :rtf diff --git a/config/initializers/new_framework_defaults_6_0.rb b/config/initializers/new_framework_defaults_6_0.rb deleted file mode 100644 index 0c410fe..0000000 --- a/config/initializers/new_framework_defaults_6_0.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -# Be sure to restart your server when you modify this file. -# -# This file contains migration options to ease your Rails 6.0 upgrade. -# -# Once upgraded flip defaults one by one to migrate to the new default. -# -# Read the Guide for Upgrading Ruby on Rails for more info on each option. - -# Don't force requests from old versions of IE to be UTF-8 encoded. -# Rails.application.config.action_view.default_enforce_utf8 = false - -# Embed purpose and expiry metadata inside signed and encrypted -# cookies for increased security. -# -# This option is not backwards compatible with earlier Rails versions. -# It's best enabled when your entire app is migrated and stable on 6.0. -# Rails.application.config.action_dispatch.use_cookies_with_metadata = true - -# Change the return value of `ActionDispatch::Response#content_type` to Content-Type header without modification. -# Rails.application.config.action_dispatch.return_only_media_type_on_content_type = false - -# Return false instead of self when enqueuing is aborted from a callback. -# Rails.application.config.active_job.return_false_on_aborted_enqueue = true - -# Send Active Storage analysis and purge jobs to dedicated queues. -# Rails.application.config.active_storage.queues.analysis = :active_storage_analysis -# Rails.application.config.active_storage.queues.purge = :active_storage_purge - -# When assigning to a collection of attachments declared via `has_many_attached`, replace existing -# attachments instead of appending. Use #attach to add new attachments without replacing existing ones. -# Rails.application.config.active_storage.replace_on_assign_to_many = true - -# Use ActionMailer::MailDeliveryJob for sending parameterized and normal mail. -# -# The default delivery jobs (ActionMailer::Parameterized::DeliveryJob, ActionMailer::DeliveryJob), -# will be removed in Rails 6.1. This setting is not backwards compatible with earlier Rails versions. -# If you send mail in the background, job workers need to have a copy of -# MailDeliveryJob to ensure all delivery jobs are processed properly. -# Make sure your entire app is migrated and stable on 6.0 before using this setting. -# Rails.application.config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob" - -# Enable the same cache key to be reused when the object being cached of type -# `ActiveRecord::Relation` changes by moving the volatile information (max updated at and count) -# of the relation's cache key into the cache version to support recycling cache key. -# Rails.application.config.active_record.collection_cache_versioning = true diff --git a/config/initializers/pinglish.rb b/config/initializers/pinglish.rb deleted file mode 100644 index 502bf29..0000000 --- a/config/initializers/pinglish.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -shared_checks = lambda do |ping| - ping.check do - true - end - - ping.check :db do - ActiveRecord::Base.connection.active? - end -end - -Rails.application.config.middleware.use Pinglish, path: "/_heartbeat", &shared_checks - -Rails.application.config.middleware.use Pinglish, path: "/_ping" do |ping| - shared_checks.call ping - - ping.check :branch do - Rails.root.join("BRANCH").read.chomp - end - - ping.check :commit do - Rails.root.join("COMMIT").read.chomp - end - - ping.check :version do - Rails.root.join("VERSION").read.chomp - end -end diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb deleted file mode 100644 index 256dd85..0000000 --- a/config/initializers/sentry.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -return if ENV["ASSETS_PRECOMPILE"].present? - -Sentry.init do |config| - config.dsn = Rails.application.credentials.dig(:error_api) - config.breadcrumbs_logger += [:active_support_logger] - config.enabled_environments = %w[review staging production] -end diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb deleted file mode 100644 index a0f72fe..0000000 --- a/config/initializers/sidekiq.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -require "sidekiq" -require "sidekiq-scheduler" -require "redis_config_builder" - -redis_conn = proc { Redis.new(RedisConfigBuilder.build("sidekiq")) } - -# This is the recommendation from sidekiq-scheduler: -# https://github.com/moove-it/sidekiq-scheduler#notes-about-connection-pooling -redis_pool_size = Sidekiq.options[:concurrency] + 5 - -Sidekiq.configure_server do |config| - config.redis = ConnectionPool.new(size: redis_pool_size, &redis_conn) - - # https://github.com/mperham/sidekiq/issues/4496#issuecomment-677838552 - config.death_handlers << ->(job, exception) do - worker = job["wrapped"].safe_constantize - worker&.sidekiq_retries_exhausted_block&.call(job, exception) - end -end - -Sidekiq.configure_client do |config| - config.redis = ConnectionPool.new(size: redis_pool_size, &redis_conn) -end - -Sidekiq.default_worker_options = {retry: 3} diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb deleted file mode 100644 index 2f3c0db..0000000 --- a/config/initializers/wrap_parameters.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -# Be sure to restart your server when you modify this file. - -# This file contains settings for ActionController::ParamsWrapper which -# is enabled by default. - -# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. -ActiveSupport.on_load(:action_controller) do - wrap_parameters format: [:json] -end - -# To enable root element in JSON for ActiveRecord objects. -# ActiveSupport.on_load(:active_record) do -# self.include_root_in_json = true -# end diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml deleted file mode 100644 index 0b8f130..0000000 --- a/config/locales/devise.en.yml +++ /dev/null @@ -1,64 +0,0 @@ -# Additional translations at https://github.com/plataformatec/devise/wiki/I18n - -en: - devise: - confirmations: - confirmed: "Your email address has been successfully confirmed." - send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes." - send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes." - failure: - already_authenticated: "You are already signed in." - inactive: "Your account is not activated yet." - invalid: "Invalid %{authentication_keys} or password." - locked: "Your account is locked." - last_attempt: "You have one more attempt before your account is locked." - not_found_in_database: "Invalid %{authentication_keys} or password." - timeout: "Your session expired. Please sign in again to continue." - unauthenticated: "You need to sign in or sign up before continuing." - unconfirmed: "You have to confirm your email address before continuing." - mailer: - confirmation_instructions: - subject: "Confirmation instructions" - reset_password_instructions: - subject: "Reset password instructions" - unlock_instructions: - subject: "Unlock instructions" - email_changed: - subject: "Email Changed" - password_change: - subject: "Password Changed" - omniauth_callbacks: - failure: "Could not authenticate you from %{kind} because \"%{reason}\"." - success: "Successfully authenticated from %{kind} account." - passwords: - no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." - send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." - send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." - updated: "Your password has been changed successfully. You are now signed in." - updated_not_active: "Your password has been changed successfully." - registrations: - destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." - signed_up: "Welcome! You have signed up successfully." - signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." - signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." - signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." - update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address." - updated: "Your account has been updated successfully." - sessions: - signed_in: "Signed in successfully." - signed_out: "Signed out successfully." - already_signed_out: "Signed out successfully." - unlocks: - send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." - send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." - unlocked: "Your account has been unlocked successfully. Please sign in to continue." - errors: - messages: - already_confirmed: "was already confirmed, please try signing in" - confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" - expired: "has expired, please request a new one" - not_found: "not found" - not_locked: "was not locked" - not_saved: - one: "1 error prohibited this %{resource} from being saved:" - other: "%{count} errors prohibited this %{resource} from being saved:" diff --git a/config/locales/en.yml b/config/locales/en.yml deleted file mode 100644 index 753ef4b..0000000 --- a/config/locales/en.yml +++ /dev/null @@ -1,128 +0,0 @@ -en: - attributes: - created_at: "Created at" - updated_at: "Updated at" - created: Record was created successfully - updated: Record was updated successfully - activity_types: - received: Received - rerouted: Rerouted to Owner - delivered: Delivered - opened: Opened - click: Clicked - bounced: Bounced - blocked: Blocked - scheduled: Scheduled - sent: Sent - recipient_types: - to: Recipient - cc: CC - bcc: BCC - rerouted: - Hermes intercepted the following email and prevented it from being delivered to its intended recipients. - If you believe this is an error, please contact your Hermes Administrator. - helpers: - select: - prompt: "- Please select -" - submit: - create: "Create" - submit: Save %{model} - update: "Save changes" - label: - client: - api_key: "API Key" - api_secret: "API Secret" - is_active: "Grant access to the Hermes API" - are_emails_sent: "Sent emails to requested recipients" - message: - to: "Recipient" - activerecord: - attributes: - client_upload: - file_types: - subscriber: Subscriber Bulk Import - subscription: - statuses: - active: Active - inactive: Inactive - paused: Paused - client_environment: - status: Delivery Policy - errors: - messages: - record_invalid: "Validation failed: %{errors}" - restrict_dependent_destroy: - has_one: "Cannot delete record because a dependent %{record} exists" - has_many: "Cannot delete record because dependent %{record} exist" - date: - formats: - default: "%m-%d-%Y" - long: "%B %d, %Y" - short: "%b %d" - order: - - :month - - :day - - :year - time: - am: am - pm: pm - formats: - default: "%m/%d/%Y %H:%M:%S" - long: "%a, %d %b %Y %I:%M:%S %p %Z" - short: "%m/%d/%y %I:%M %p" - errors: - messages: - something: "" - number: - currency: - format: - delimiter: "," - format: "%u%n" - precision: 2 - separator: "." - significant: false - strip_insignificant_zeros: false - unit: "$" - format: - delimiter: "," - precision: 3 - separator: "." - significant: false - strip_insignificant_zeros: false - human: - decimal_units: - format: "%n %u" - units: - billion: Billion - million: Million - quadrillion: Quadrillion - thousand: Thousand - trillion: Trillion - unit: "" - format: - delimiter: "" - precision: 3 - significant: true - strip_insignificant_zeros: true - storage_units: - format: "%n %u" - units: - byte: - one: Byte - other: Bytes - gb: GB - kb: KB - mb: MB - tb: TB - percentage: - format: - delimiter: "" - format: "%n%" - precision: - format: - delimiter: "" - support: - array: - last_word_connector: ", and " - two_words_connector: " and " - words_connector: ", " diff --git a/config/puma.rb b/config/puma.rb deleted file mode 100644 index fef891b..0000000 --- a/config/puma.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -# Puma can serve each request in a thread from an internal thread pool. -# The `threads` method setting takes two numbers: a minimum and maximum. -# Any libraries that use thread pools should be configured to match -# the maximum value specified for Puma. Default is set to 5 threads for minimum -# and maximum; this matches the default thread size of Active Record. -# -max_threads_count = ENV.fetch("RAILS_MAX_THREADS", 5) -min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } -threads min_threads_count, max_threads_count - -# Specifies the `port` that Puma will listen on to receive requests; default is 3000. -# -port ENV.fetch("PORT", 3000) - -# Specifies the `environment` that Puma will run in. -# -environment ENV.fetch("RAILS_ENV", "development") - -# Specifies the `pidfile` that Puma will use. -pidfile ENV.fetch("PIDFILE", "tmp/pids/server.pid") - -# Specifies the number of `workers` to boot in clustered mode. -# Workers are forked web server processes. If using threads and workers together -# the concurrency of the application would be max `threads` * `workers`. -# Workers do not work on JRuby or Windows (both of which do not support -# processes). -# -# workers ENV.fetch("WEB_CONCURRENCY") { 2 } - -# Use the `preload_app!` method when specifying a `workers` number. -# This directive tells Puma to first boot the application and load code -# before forking the application. This takes advantage of Copy On Write -# process behavior so workers use less memory. -# -# preload_app! - -# Allow puma to be restarted by `rails restart` command. -plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb deleted file mode 100644 index be23012..0000000 --- a/config/routes.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -require "sidekiq/web" - -Rails.application.routes.draw do - root to: "home#index", as: "home" - - namespace :api do - post "messages", to: "messages#new" - post "notifications", to: "notifications#new" - end - - devise_for :users, path: "security" - concern :paginatable do - get "(page/:page)", action: :index, on: :collection, as: "" - end - - authenticate :user do - mount Sidekiq::Web => "/sidekiq" - - resources :clients, except: %i[delete] do - get "messages", to: "clients#messages", as: "messages" - get "new_email", to: "clients#new_email", as: "new_email" - post "send_email", to: "clients#send_email", as: "send_email" - resources :client_environments, path: :permissions, as: :environments, except: %i[delete] - resources :client_uploads, path: :uploads, as: :uploads, except: %i[delete] - resources :mailing_topics, path: :topics, as: :topics, except: %i[delete] - resources :subscribers, except: %i[delete] - resources :templates, except: %i[delete] - end - resources :messages, param: :tracking_id, only: %i[index show] do - get "preview", action: :preview, as: "preview" - get "logs", action: :logs, as: "logs" - get "recipients", action: :recipients, as: "recipients" - end - resources :subscriptions, only: %i[index edit update] - end -end diff --git a/config/spring.rb b/config/spring.rb deleted file mode 100644 index 37a3543..0000000 --- a/config/spring.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -Spring.watch( - ".ruby-version", - ".rbenv-vars", - "tmp/restart.txt", - "tmp/caching-dev.txt" -) diff --git a/config/storage.yml b/config/storage.yml deleted file mode 100644 index eb09d1c..0000000 --- a/config/storage.yml +++ /dev/null @@ -1,15 +0,0 @@ -test: - service: Disk - root: <%= Rails.root.join("tmp/storage") %> - -local: - service: Disk - root: <%= Rails.root.join("storage") %> - -amazon: - service: S3 - access_key_id: <%= Rails.application.credentials.dig(:storage, :key) %> - secret_access_key: <%= Rails.application.credentials.dig(:storage, :secret) %> - region: nyc3 - bucket: <%= ENV.fetch('STORAGE_BUCKET') %> - endpoint: "https://nyc3.digitaloceanspaces.com" diff --git a/config/webpack/development.js b/config/webpack/development.js deleted file mode 100644 index c5edff9..0000000 --- a/config/webpack/development.js +++ /dev/null @@ -1,5 +0,0 @@ -process.env.NODE_ENV = process.env.NODE_ENV || 'development' - -const environment = require('./environment') - -module.exports = environment.toWebpackConfig() diff --git a/config/webpack/environment.js b/config/webpack/environment.js deleted file mode 100644 index d16d9af..0000000 --- a/config/webpack/environment.js +++ /dev/null @@ -1,3 +0,0 @@ -const { environment } = require('@rails/webpacker') - -module.exports = environment diff --git a/config/webpack/production.js b/config/webpack/production.js deleted file mode 100644 index be0f53a..0000000 --- a/config/webpack/production.js +++ /dev/null @@ -1,5 +0,0 @@ -process.env.NODE_ENV = process.env.NODE_ENV || 'production' - -const environment = require('./environment') - -module.exports = environment.toWebpackConfig() diff --git a/config/webpack/test.js b/config/webpack/test.js deleted file mode 100644 index c5edff9..0000000 --- a/config/webpack/test.js +++ /dev/null @@ -1,5 +0,0 @@ -process.env.NODE_ENV = process.env.NODE_ENV || 'development' - -const environment = require('./environment') - -module.exports = environment.toWebpackConfig() diff --git a/config/webpacker.yml b/config/webpacker.yml deleted file mode 100644 index f7f16dd..0000000 --- a/config/webpacker.yml +++ /dev/null @@ -1,84 +0,0 @@ -# Note: You must restart bin/webpack-dev-server for changes to take effect - -default: &default - source_path: app/javascript - source_entry_path: packs - public_root_path: public - public_output_path: packs - cache_path: tmp/cache/webpacker - check_yarn_integrity: false - webpack_compile_output: true - - # Additional paths webpack should lookup modules - # ['app/assets', 'engine/foo/app/assets'] - additional_paths: [] - - # Reload manifest.json on all requests so we reload latest compiled packs - cache_manifest: false - - # Extract and emit a css file - extract_css: false - - static_assets_extensions: - - .jpg - - .jpeg - - .png - - .gif - - .tiff - - .ico - - .svg - - .eot - - .otf - - .ttf - - .woff - - .woff2 - - extensions: - - .mjs - - .js - - .sass - - .scss - - .css - - .module.sass - - .module.scss - - .module.css - - .png - - .svg - - .gif - - .jpeg - - .jpg - -development: - <<: *default - compile: true - - # Reference: https://webpack.js.org/configuration/dev-server/ - dev_server: - https: false - host: localhost - port: 3035 - public: localhost:3035 - hmr: false - # Inline should be set to true if using HMR - inline: false - overlay: true - compress: true - disable_host_check: true - use_local_ip: false - quiet: false - pretty: false - headers: - 'Access-Control-Allow-Origin': '*' - watch_options: - ignored: '**/node_modules/**' - -test: - <<: *default - compile: true - public_output_path: packs-test - -production: - <<: *default - compile: false - extract_css: true - cache_manifest: true diff --git a/db/migrate/20181129033057_create_clients.rb b/db/migrate/20181129033057_create_clients.rb deleted file mode 100644 index 37da67e..0000000 --- a/db/migrate/20181129033057_create_clients.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -class CreateClients < ActiveRecord::Migration[5.2] - def change - create_table :clients do |t| - t.string :name, null: false, length: {maximum: 50}, index: {unique: true} - t.string :owner, null: false, length: {maximum: 50} - t.string :reroute_email, null: false, length: {maximum: 60} - t.string :api_secret, null: false, length: {maximum: 128}, index: {unique: true} - t.string :api_key, null: false, length: {maximum: 128}, index: {unique: true} - t.boolean :is_active, null: false, default: false - t.boolean :are_emails_sent, null: false, default: false - t.timestamps - end - end -end diff --git a/db/migrate/20181130001936_devise_create_users.rb b/db/migrate/20181130001936_devise_create_users.rb deleted file mode 100644 index 8aa52b8..0000000 --- a/db/migrate/20181130001936_devise_create_users.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -class DeviseCreateUsers < ActiveRecord::Migration[5.2] - def change - create_table :users do |t| - t.string :name, null: false - t.string :email, null: false, default: "" - t.string :encrypted_password, null: false, default: "" - t.string :reset_password_token - t.datetime :reset_password_sent_at - t.datetime :remember_created_at - t.integer :sign_in_count, default: 0, null: false - t.datetime :current_sign_in_at - t.datetime :last_sign_in_at - t.inet :current_sign_in_ip - t.inet :last_sign_in_ip - t.string :confirmation_token - t.datetime :confirmed_at - t.datetime :confirmation_sent_at - t.string :unconfirmed_email - t.integer :failed_attempts, default: 0, null: false - t.datetime :locked_at - t.timestamps null: false - end - - add_index :users, :email, unique: true - add_index :users, :reset_password_token, unique: true - add_index :users, :confirmation_token, unique: true - end -end diff --git a/db/migrate/20181130025912_create_mail_logs.rb b/db/migrate/20181130025912_create_mail_logs.rb deleted file mode 100644 index 8add8d6..0000000 --- a/db/migrate/20181130025912_create_mail_logs.rb +++ /dev/null @@ -1,16 +0,0 @@ -class CreateMailLogs < ActiveRecord::Migration[5.2] - def change - create_table :mail_logs do |t| - t.string :from - t.string :to, null: false - t.string :cc - t.string :bcc - t.string :subject, null: false - t.string :body - t.string :type - t.boolean :was_rerouted, null: false - t.belongs_to :client, null: false - t.timestamps - end - end -end diff --git a/db/migrate/20181201025601_rename_type_to_content_type_on_mail_logs.rb b/db/migrate/20181201025601_rename_type_to_content_type_on_mail_logs.rb deleted file mode 100644 index b1ccbe7..0000000 --- a/db/migrate/20181201025601_rename_type_to_content_type_on_mail_logs.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RenameTypeToContentTypeOnMailLogs < ActiveRecord::Migration[5.2] - def change - rename_column :mail_logs, :type, :content_type - end -end diff --git a/db/migrate/20181203045905_add_environment_to_api.rb b/db/migrate/20181203045905_add_environment_to_api.rb deleted file mode 100644 index 6154ac0..0000000 --- a/db/migrate/20181203045905_add_environment_to_api.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddEnvironmentToApi < ActiveRecord::Migration[5.2] - def change - add_column :mail_logs, :environment, :string, null: false - end -end diff --git a/db/migrate/20181203192943_create_read_receipts.rb b/db/migrate/20181203192943_create_read_receipts.rb deleted file mode 100644 index 3ced1f4..0000000 --- a/db/migrate/20181203192943_create_read_receipts.rb +++ /dev/null @@ -1,22 +0,0 @@ -class CreateReadReceipts < ActiveRecord::Migration[5.2] - def change - enable_extension "pgcrypto" unless extension_enabled?("pgcrypto") - - add_column :mail_logs, :tracking_id, :string, null: false, default: "" - - create_table :read_receipts do |t| - t.belongs_to :mail_log, null: false - t.string :remote_ip - t.string :user_agent - t.string :filename - t.timestamps - end - - create_table :read_receipts_queries do |t| - t.belongs_to :read_receipt, null: false - t.string :field - t.string :value - t.timestamps - end - end -end diff --git a/db/migrate/20190721042119_create_message_activity.rb b/db/migrate/20190721042119_create_message_activity.rb deleted file mode 100644 index 639230a..0000000 --- a/db/migrate/20190721042119_create_message_activity.rb +++ /dev/null @@ -1,57 +0,0 @@ -class CreateMessageActivity < ActiveRecord::Migration[5.2] - def change - drop_table :read_receipts_queries - drop_table :read_receipts - drop_table :mail_logs - - create_table :messages do |t| - t.belongs_to :client, null: false - t.string :sender - t.string :subject, null: false - t.string :body - t.string :content_type - t.string :priority - t.string :environment - t.string :tracking_id - t.datetime :sent_at - t.timestamps - end - - create_table :message_recipients do |t| - t.belongs_to :message, null: false - t.string :email - t.string :recipient_type - t.datetime :send_at - t.datetime :delivered_at - t.timestamps - end - - create_table :message_activities do |t| - t.belongs_to :message, null: false - t.string :activity_type - t.string :activity_details - t.string :ip_address - t.string :user_agent - t.string :link_url - t.string :reject_reason - t.string :reporting_mta - t.string :smtp_response - t.string :bounce_type - t.string :feedback_id - t.string :complaint_type - t.datetime :complaint_arrival_date - t.datetime :notification_timestamp - t.timestamps - end - - create_table :message_activity_recipients do |t| - t.belongs_to :message_activity, null: false - t.belongs_to :message_recipient, null: false - t.string :action - t.string :status - t.string :diagnosticCode - t.datetime :notification_timestamp - t.timestamps - end - end -end diff --git a/db/migrate/20200901160838_create_client_environments.rb b/db/migrate/20200901160838_create_client_environments.rb deleted file mode 100644 index 13a499e..0000000 --- a/db/migrate/20200901160838_create_client_environments.rb +++ /dev/null @@ -1,20 +0,0 @@ -class CreateClientEnvironments < ActiveRecord::Migration[6.0] - def change - create_table :callbacks do |t| - t.string :data, null: false, default: false - t.string :status, null: false, default: false - t.timestamps - end - - create_table :client_environments do |t| - t.belongs_to :client, null: false - t.string :name, null: false, default: false - t.string :status, null: false, default: false - t.timestamps - end - - add_column :clients, :reply_to_email, :string - rename_column :messages, :body, :html_body - add_column :messages, :text_body, :string - end -end diff --git a/db/migrate/20200901221528_add_remaining_fields.rb b/db/migrate/20200901221528_add_remaining_fields.rb deleted file mode 100644 index 2f231f1..0000000 --- a/db/migrate/20200901221528_add_remaining_fields.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddRemainingFields < ActiveRecord::Migration[6.0] - def change - add_column :message_activities, :bounce_subtype, :string - add_column :message_activities, :delay_type, :string - add_column :message_activities, :expiration_time, :datetime - end -end diff --git a/db/migrate/20200906074526_create_templates.rb b/db/migrate/20200906074526_create_templates.rb deleted file mode 100644 index ec82ea8..0000000 --- a/db/migrate/20200906074526_create_templates.rb +++ /dev/null @@ -1,15 +0,0 @@ -class CreateTemplates < ActiveRecord::Migration[6.0] - def change - create_table :templates do |t| - t.belongs_to :client, null: false, foreign_key: true, index: true - t.string :name - t.string :sender_name - t.string :sender_address - t.string :html_body - t.string :text_body - t.string :json_layout - t.boolean :active - t.timestamps - end - end -end diff --git a/db/migrate/20200906074539_create_mailing_topics.rb b/db/migrate/20200906074539_create_mailing_topics.rb deleted file mode 100644 index 6ce5793..0000000 --- a/db/migrate/20200906074539_create_mailing_topics.rb +++ /dev/null @@ -1,26 +0,0 @@ -class CreateMailingTopics < ActiveRecord::Migration[6.0] - def change - create_table :mailing_topics do |t| - t.belongs_to :client, null: false, foreign_key: true, index: true - t.string :name - t.string :description - t.boolean :active - t.timestamps - end - - create_table :subscribers do |t| - t.belongs_to :client, null: false, foreign_key: true, index: true - t.string :name - t.string :address - t.timestamps - end - - create_table :subscriptions do |t| - t.belongs_to :mailing_topic, null: false, foreign_key: true, index: true - t.belongs_to :subscriber, null: false, foreign_key: true, index: true - t.string :status - t.string :memo - t.timestamps - end - end -end diff --git a/db/migrate/20200915033340_missing_foreign_keys.rb b/db/migrate/20200915033340_missing_foreign_keys.rb deleted file mode 100644 index 3bda306..0000000 --- a/db/migrate/20200915033340_missing_foreign_keys.rb +++ /dev/null @@ -1,10 +0,0 @@ -class MissingForeignKeys < ActiveRecord::Migration[6.0] - def change - add_foreign_key :messages, :clients - add_foreign_key :message_recipients, :messages - add_foreign_key :client_environments, :clients - add_foreign_key :message_activities, :messages - add_foreign_key :message_activity_recipients, :message_activities - add_foreign_key :message_activity_recipients, :message_recipients - end -end diff --git a/db/migrate/20200915051422_remove_client_environment_defaults.rb b/db/migrate/20200915051422_remove_client_environment_defaults.rb deleted file mode 100644 index effadf8..0000000 --- a/db/migrate/20200915051422_remove_client_environment_defaults.rb +++ /dev/null @@ -1,6 +0,0 @@ -class RemoveClientEnvironmentDefaults < ActiveRecord::Migration[6.0] - def change - change_column_default :client_environments, :name, from: "f", to: nil - change_column_default :client_environments, :status, from: "f", to: nil - end -end diff --git a/db/migrate/20200915200614_improve_subscriptions.rb b/db/migrate/20200915200614_improve_subscriptions.rb deleted file mode 100644 index e9246ca..0000000 --- a/db/migrate/20200915200614_improve_subscriptions.rb +++ /dev/null @@ -1,11 +0,0 @@ -class ImproveSubscriptions < ActiveRecord::Migration[6.0] - def up - change_column :subscriptions, :status, :integer, using: "status::integer" - add_column :subscriptions, :identifier, :string, null: false - end - - def down - change_column :subscriptions, :status, :string - remove_column :subscriptions, :identifier - end -end diff --git a/db/migrate/20200915201651_add_missing_indexes.rb b/db/migrate/20200915201651_add_missing_indexes.rb deleted file mode 100644 index faa245a..0000000 --- a/db/migrate/20200915201651_add_missing_indexes.rb +++ /dev/null @@ -1,11 +0,0 @@ -class AddMissingIndexes < ActiveRecord::Migration[6.0] - def change - add_index :client_environments, %i[client_id name], unique: true - add_index :mailing_topics, %i[client_id name], unique: true - add_index :subscribers, %i[client_id address], unique: true - add_index :subscriptions, %i[mailing_topic_id subscriber_id], unique: true - add_index :subscriptions, :identifier, unique: true - add_index :subscriptions, :status - add_index :templates, %i[client_id name], unique: true - end -end diff --git a/db/migrate/20200915202953_create_active_storage_tables.active_storage.rb b/db/migrate/20200915202953_create_active_storage_tables.active_storage.rb deleted file mode 100644 index fd86aef..0000000 --- a/db/migrate/20200915202953_create_active_storage_tables.active_storage.rb +++ /dev/null @@ -1,27 +0,0 @@ -# This migration comes from active_storage (originally 20170806125915) -class CreateActiveStorageTables < ActiveRecord::Migration[5.2] - def change - create_table :active_storage_blobs do |t| - t.string :key, null: false - t.string :filename, null: false - t.string :content_type - t.text :metadata - t.bigint :byte_size, null: false - t.string :checksum, null: false - t.datetime :created_at, null: false - - t.index [:key], unique: true - end - - create_table :active_storage_attachments do |t| - t.string :name, null: false - t.references :record, null: false, polymorphic: true, index: false - t.references :blob, null: false - - t.datetime :created_at, null: false - - t.index [:record_type, :record_id, :name, :blob_id], name: "index_active_storage_attachments_uniqueness", unique: true - t.foreign_key :active_storage_blobs, column: :blob_id - end - end -end diff --git a/db/migrate/20200918063434_create_client_uploads.rb b/db/migrate/20200918063434_create_client_uploads.rb deleted file mode 100644 index 2c897c6..0000000 --- a/db/migrate/20200918063434_create_client_uploads.rb +++ /dev/null @@ -1,10 +0,0 @@ -class CreateClientUploads < ActiveRecord::Migration[6.0] - def change - create_table :client_uploads do |t| - t.belongs_to :client, null: false, foreign_key: true, index: true - t.string :file_type - t.string :status - t.timestamps - end - end -end diff --git a/db/migrate/20210328002100_create_action_text_tables.action_text.rb b/db/migrate/20210328002100_create_action_text_tables.action_text.rb deleted file mode 100644 index 191a034..0000000 --- a/db/migrate/20210328002100_create_action_text_tables.action_text.rb +++ /dev/null @@ -1,14 +0,0 @@ -# This migration comes from action_text (originally 20180528164100) -class CreateActionTextTables < ActiveRecord::Migration[6.0] - def change - create_table :action_text_rich_texts do |t| - t.string :name, null: false - t.text :body, size: :long - t.references :record, null: false, polymorphic: true, index: false - - t.timestamps - - t.index [:record_type, :record_id, :name], name: "index_action_text_rich_texts_uniqueness", unique: true - end - end -end diff --git a/db/migrate/20210328005405_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb b/db/migrate/20210328005405_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb deleted file mode 100644 index ff5d72c..0000000 --- a/db/migrate/20210328005405_add_foreign_key_constraint_to_active_storage_attachments_for_blob_id.active_storage.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from active_storage (originally 20180723000244) -class AddForeignKeyConstraintToActiveStorageAttachmentsForBlobId < ActiveRecord::Migration[6.0] - def up - return if foreign_key_exists?(:active_storage_attachments, column: :blob_id) - - if table_exists?(:active_storage_blobs) - add_foreign_key :active_storage_attachments, :active_storage_blobs, column: :blob_id - end - end -end diff --git a/db/migrate/20210813191801_add_regex_to_environments.rb b/db/migrate/20210813191801_add_regex_to_environments.rb deleted file mode 100644 index e3d3bb7..0000000 --- a/db/migrate/20210813191801_add_regex_to_environments.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddRegexToEnvironments < ActiveRecord::Migration[6.0] - def change - add_column :client_environments, :regex, :boolean, default: false, null: false - end -end diff --git a/db/schema.rb b/db/schema.rb deleted file mode 100644 index c85e508..0000000 --- a/db/schema.rb +++ /dev/null @@ -1,245 +0,0 @@ -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# This file is the source Rails uses to define your schema when running `rails -# db:schema:load`. When creating a new database, `rails db:schema:load` tends to -# be faster and is potentially less error prone than running all of your -# migrations from scratch. Old migrations may fail to apply correctly if those -# migrations use external dependencies or application code. -# -# It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema.define(version: 2021_08_13_191801) do - - # These are extensions that must be enabled in order to support this database - enable_extension "pgcrypto" - enable_extension "plpgsql" - - create_table "action_text_rich_texts", force: :cascade do |t| - t.string "name", null: false - t.text "body" - t.string "record_type", null: false - t.bigint "record_id", null: false - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true - end - - create_table "active_storage_attachments", force: :cascade do |t| - t.string "name", null: false - t.string "record_type", null: false - t.bigint "record_id", null: false - t.bigint "blob_id", null: false - t.datetime "created_at", null: false - t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" - t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true - end - - create_table "active_storage_blobs", force: :cascade do |t| - t.string "key", null: false - t.string "filename", null: false - t.string "content_type" - t.text "metadata" - t.bigint "byte_size", null: false - t.string "checksum", null: false - t.datetime "created_at", null: false - t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true - end - - create_table "callbacks", force: :cascade do |t| - t.string "data", default: "f", null: false - t.string "status", default: "f", null: false - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - end - - create_table "client_environments", force: :cascade do |t| - t.bigint "client_id", null: false - t.string "name", null: false - t.string "status", null: false - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.boolean "regex", default: false, null: false - t.index ["client_id", "name"], name: "index_client_environments_on_client_id_and_name", unique: true - t.index ["client_id"], name: "index_client_environments_on_client_id" - end - - create_table "client_uploads", force: :cascade do |t| - t.bigint "client_id", null: false - t.string "file_type" - t.string "status" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["client_id"], name: "index_client_uploads_on_client_id" - end - - create_table "clients", force: :cascade do |t| - t.string "name", null: false - t.string "owner", null: false - t.string "reroute_email", null: false - t.string "api_secret", null: false - t.string "api_key", null: false - t.boolean "is_active", default: false, null: false - t.boolean "are_emails_sent", default: false, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "reply_to_email" - t.index ["api_key"], name: "index_clients_on_api_key", unique: true - t.index ["api_secret"], name: "index_clients_on_api_secret", unique: true - t.index ["name"], name: "index_clients_on_name", unique: true - end - - create_table "mailing_topics", force: :cascade do |t| - t.bigint "client_id", null: false - t.string "name" - t.string "description" - t.boolean "active" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["client_id", "name"], name: "index_mailing_topics_on_client_id_and_name", unique: true - t.index ["client_id"], name: "index_mailing_topics_on_client_id" - end - - create_table "message_activities", force: :cascade do |t| - t.bigint "message_id", null: false - t.string "activity_type" - t.string "activity_details" - t.string "ip_address" - t.string "user_agent" - t.string "link_url" - t.string "reject_reason" - t.string "reporting_mta" - t.string "smtp_response" - t.string "bounce_type" - t.string "feedback_id" - t.string "complaint_type" - t.datetime "complaint_arrival_date" - t.datetime "notification_timestamp" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "bounce_subtype" - t.string "delay_type" - t.datetime "expiration_time" - t.index ["message_id"], name: "index_message_activities_on_message_id" - end - - create_table "message_activity_recipients", force: :cascade do |t| - t.bigint "message_activity_id", null: false - t.bigint "message_recipient_id", null: false - t.string "action" - t.string "status" - t.string "diagnosticCode" - t.datetime "notification_timestamp" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["message_activity_id"], name: "index_message_activity_recipients_on_message_activity_id" - t.index ["message_recipient_id"], name: "index_message_activity_recipients_on_message_recipient_id" - end - - create_table "message_recipients", force: :cascade do |t| - t.bigint "message_id", null: false - t.string "email" - t.string "recipient_type" - t.datetime "send_at" - t.datetime "delivered_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["message_id"], name: "index_message_recipients_on_message_id" - end - - create_table "messages", force: :cascade do |t| - t.bigint "client_id", null: false - t.string "sender" - t.string "subject", null: false - t.string "html_body" - t.string "content_type" - t.string "priority" - t.string "environment" - t.string "tracking_id" - t.datetime "sent_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "text_body" - t.index ["client_id"], name: "index_messages_on_client_id" - end - - create_table "subscribers", force: :cascade do |t| - t.bigint "client_id", null: false - t.string "name" - t.string "address" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["client_id", "address"], name: "index_subscribers_on_client_id_and_address", unique: true - t.index ["client_id"], name: "index_subscribers_on_client_id" - end - - create_table "subscriptions", force: :cascade do |t| - t.bigint "mailing_topic_id", null: false - t.bigint "subscriber_id", null: false - t.integer "status" - t.string "memo" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.string "identifier", null: false - t.index ["identifier"], name: "index_subscriptions_on_identifier", unique: true - t.index ["mailing_topic_id", "subscriber_id"], name: "index_subscriptions_on_mailing_topic_id_and_subscriber_id", unique: true - t.index ["mailing_topic_id"], name: "index_subscriptions_on_mailing_topic_id" - t.index ["status"], name: "index_subscriptions_on_status" - t.index ["subscriber_id"], name: "index_subscriptions_on_subscriber_id" - end - - create_table "templates", force: :cascade do |t| - t.bigint "client_id", null: false - t.string "name" - t.string "sender_name" - t.string "sender_address" - t.string "html_body" - t.string "text_body" - t.string "json_layout" - t.boolean "active" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["client_id", "name"], name: "index_templates_on_client_id_and_name", unique: true - t.index ["client_id"], name: "index_templates_on_client_id" - end - - create_table "users", force: :cascade do |t| - t.string "name", null: false - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" - t.datetime "reset_password_sent_at" - t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0, null: false - t.datetime "current_sign_in_at" - t.datetime "last_sign_in_at" - t.inet "current_sign_in_ip" - t.inet "last_sign_in_ip" - t.string "confirmation_token" - t.datetime "confirmed_at" - t.datetime "confirmation_sent_at" - t.string "unconfirmed_email" - t.integer "failed_attempts", default: 0, null: false - t.datetime "locked_at" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true - t.index ["email"], name: "index_users_on_email", unique: true - t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true - end - - add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" - add_foreign_key "client_environments", "clients" - add_foreign_key "client_uploads", "clients" - add_foreign_key "mailing_topics", "clients" - add_foreign_key "message_activities", "messages" - add_foreign_key "message_activity_recipients", "message_activities" - add_foreign_key "message_activity_recipients", "message_recipients" - add_foreign_key "message_recipients", "messages" - add_foreign_key "messages", "clients" - add_foreign_key "subscribers", "clients" - add_foreign_key "subscriptions", "mailing_topics" - add_foreign_key "subscriptions", "subscribers" - add_foreign_key "templates", "clients" -end diff --git a/db/seeds.rb b/db/seeds.rb deleted file mode 100644 index f5d0265..0000000 --- a/db/seeds.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -unless User.where(email: Rails.application.credentials[:support][:key]).any? - User.create!(name: "Justin Adkins", - email: Rails.application.credentials[:support][:key], - password: Rails.application.credentials[:support][:secret], - confirmed_at: DateTime.now) -end - -Client.create(name: "Demo Application", - owner: "Justin Adkins", - reroute_email: "justin.adkins@mythcoders.com", - is_active: true, - are_emails_sent: false, - api_key: "speak", - api_secret: "friend") diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 0e5f12d..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,59 +0,0 @@ -version: "3.7" - -x-shared-environment-variables: &shared-environment-variables - GITLAB_ENVIRONMENT_NAME: development - ENVIRONMENT_URL: https://hermes.mythcoders.dev - NODE_ENV: development - RAILS_ENV: development - REDIS_NAMESPACE: hermes-dev - REDIS_URL: redis://myth-redis:6379/0 - REDIS_WORKER_NAMESPACE: hermes-worker-dev - SES_CONFIGSET: Hermes-Dev - STORAGE_BUCKET: mcdig-dvstg-com1 - -services: - app: - image: hermes - build: - context: . - target: base - container_name: hermes-app - command: ["sh", "./scripts/app", "start", "setup"] - labels: - - "traefik.enable=true" - - "traefik.frontend.rule=Host:hermes.mythcoders.dev" - volumes: - - .:/opt/hermes - environment: - <<: *shared-environment-variables - WEBPACKER_DEV_SERVER_HOST: webpacker - depends_on: - - webpacker - stdin_open: true - tty: true - - worker: - image: hermes - container_name: hermes-worker - command: ["sh", "./scripts/worker", "start"] - volumes: - - .:/opt/hermes - environment: - <<: *shared-environment-variables - depends_on: - - app - - webpacker: - image: hermes - container_name: hermes-webpacker - command: ["sh", "./scripts/webpack"] - environment: - <<: *shared-environment-variables - WEBPACKER_DEV_SERVER_HOST: 0.0.0.0 - volumes: - - .:/opt/hermes - -networks: - default: - name: mythcoders_dev - external: true diff --git a/lib/aws_notification.rb b/lib/aws_notification.rb deleted file mode 100644 index 571af5f..0000000 --- a/lib/aws_notification.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -class AwsNotification - IGNORED_MESSAGE = "Successfully validated SNS topic for Amazon SES event publishing." - - def initialize(raw_data) - @raw_data = raw_data - end - - def type - @type ||= if @raw_data["Type"] == "Notification" - return "SubscriptionValidation" if @raw_data["Message"] == IGNORED_MESSAGE - - # treat the eventType as the notificationType - message["eventType"].strip - else - @raw_data["Type"] - end - end - - def tracking_id - @tracking_id ||= headers.find { |header| header["name"] == "X-Hermes-ID" }["value"] - end - - def message - @message ||= JSON.parse(@raw_data["Message"]) - end - - def subscribe_url - @subscribe_url ||= @raw_data["SubscribeURL"] - end - - private - - def headers - @headers ||= message["mail"]["headers"] - end -end diff --git a/lib/bulk_upload/subscriber_importer.rb b/lib/bulk_upload/subscriber_importer.rb deleted file mode 100644 index fb23254..0000000 --- a/lib/bulk_upload/subscriber_importer.rb +++ /dev/null @@ -1,58 +0,0 @@ -# frozen_string_literal: true - -require "csv" - -module BulkUpload - class SubscriberImporter - def self.process(input) - new(input).process - end - - def initialize(data) - @row = CSV.parse(data)[0] - end - - def process - if subscriber.new_record? || subscriber.name != row[1] - update_subscriber_name - subscriber.save! - end - - return unless subscription.new_record? - - set_subscription_status - subscription.save! - end - - private - - attr_reader :row - - def mailing_topic - @mailing_topic ||= MailingTopic.find row[0] - end - - def subscriber - @subscriber ||= Subscriber.find_or_initialize_by( - client_id: mailing_topic.client_id, - address: row[2] - ) - end - - def subscription - @subscription ||= Subscription.find_or_initialize_by( - mailing_topic_id: mailing_topic.id, - subscriber_id: subscriber.id - ) - end - - def set_subscription_status - subscription.status = :active - subscription.identifier = SecureRandom.uuid - end - - def update_subscriber_name - subscriber.name = row[1] - end - end -end diff --git a/lib/hermes_app.rb b/lib/hermes_app.rb deleted file mode 100644 index 60be602..0000000 --- a/lib/hermes_app.rb +++ /dev/null @@ -1,46 +0,0 @@ -# frozen_string_literal: true - -require "pathname" - -module HermesApp - class << self - def root - Pathname.new(File.expand_path("..", __dir__)) - end - - def env_name - case Rails.env - when "development" - "DEV" - when "test" - Rails.env.case - when "review" - "REV" - else - "PROD" - end - end - - def branch - value = Rails.root.join("BRANCH").read.chomp - if value.include?("refs/") - value.sub!(%r{refs/(heads/|tags/)}, "") - else - value - end - end - - def env_url(protocol: true) - if ENV["ENVIRONMENT_URL"].present? && protocol - ENV["ENVIRONMENT_URL"].gsub("HTTP", "HTTPS").gsub("http", "https") - elsif ENV["ENVIRONMENT_URL"].present? - ENV["ENVIRONMENT_URL"].split("//").last - else - "hermes.mythcoders.dev" - end - end - end - - COMMIT = File.read(HermesApp.root.join("COMMIT")).strip.freeze - VERSION = File.read(HermesApp.root.join("VERSION")).strip.freeze -end diff --git a/lib/mail_merge.rb b/lib/mail_merge.rb deleted file mode 100644 index ebd9977..0000000 --- a/lib/mail_merge.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: true - -class MailMerge - def initialize(email_recipient) - @recipient = email_recipient - end - - def field_hash - @field_hash ||= hermes_fields.merge(contact_fields) - end - - private - - attr_reader :recipient - - def hermes_fields - { - hermes_url: HermesApp.env_url, - unsubscribe_url: subscription_url - } - end - - def contact_fields - { - contact_name: person.first_name.humanize, - contact_email: recipient.email_address.address - } - end - - def subscription_url - "#{HermesApp.env_url}/subscriptions/#{subscription_id}?tracking_id=#{tracking_id}" - end - - def subscription_id - @subscription_id ||= - Subscription.find_by( - email_address_id: recipient.email_address_id, - committee_id: committee.id - )&.identifier - end - - def tracking_id - @tracking_id ||= recipient.email_transaction.tracking_id - end -end diff --git a/lib/mailchimp/api_client.rb b/lib/mailchimp/api_client.rb deleted file mode 100644 index 5a37823..0000000 --- a/lib/mailchimp/api_client.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -module Mailchimp - class ApiClient - def self.html_to_text(html) - Faraday.post("https://templates.mailchimp.com/services/html-to-text/") do |req| - req.headers["Content-Type"] = "application/x-www-form-urlencoded; charset=utf-8" - req.body = {"html" => html} - end - rescue => e - Sentry.capture_exception e - end - end -end diff --git a/lib/message_factory.rb b/lib/message_factory.rb deleted file mode 100644 index f51a34b..0000000 --- a/lib/message_factory.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -class MessageFactory - def self.build(params, recieve_time = DateTime.Now) - message = Message.new( - client: params[:client], - from: "#{params[:sender_name]} <#{params[:sender_email]}>", - subject: params[:subject], - html_body: params[:html_body], - text_body: params[:text_body], - priority: params[:priority], - environment: params[:environment], - tracking_id: params[:tracking_id] - ) - - message.recipients << MessageRecipientFactory.build_from_array(params[:to]) - message.recipients << MessageRecipientFactory.build_from_array(params[:cc]) if params[:cc].present? - message.recipients << MessageRecipientFactory.build_from_array(params[:bcc]) if params[:bcc].present? - message.activities << MessageActivity.new(type: "Received", time: recieve_time) - message - end -end diff --git a/lib/message_recipient_factory.rb b/lib/message_recipient_factory.rb deleted file mode 100644 index be8bd20..0000000 --- a/lib/message_recipient_factory.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -class MessageRecipientFactory - def self.build_from_array(source, type) - source.each do |email| - MessageRecipient.new(email: email, recipient_type: type) - end - end -end diff --git a/lib/notification_handlers/base_notification_handler.rb b/lib/notification_handlers/base_notification_handler.rb deleted file mode 100644 index ad32c9c..0000000 --- a/lib/notification_handlers/base_notification_handler.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -module NotificationHandlers - class BaseNotificationHandler - def initialize(notification) - @notification = notification - end - - private - - def message - @message ||= Message.find_by_tracking_id! @notification.tracking_id - end - end -end diff --git a/lib/notification_handlers/bounce_handler.rb b/lib/notification_handlers/bounce_handler.rb deleted file mode 100644 index 4007def..0000000 --- a/lib/notification_handlers/bounce_handler.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -module NotificationHandlers - class BounceHandler < BaseNotificationHandler - def handle - new_callback.tap do |callback| - bounced_recipients.each do |bounced_recipient| - recipient = message.recipients.find_by_email(bounced_recipient["emailAddress"]).first - next if recipient.nil? - - callback.recipients << MessageActivityRecipient.new( - recipient: recipient, - status: bounced_recipient["status"], - action: bounced_recipient["action"], - diagnostic_code: bounced_recipient["diagnosticCode"] - ) - end - - callback.save! - end - end - - private - - def new_callback - MessageActivity.new(activity_type: :bounce, - message: message, - notification_timestamp: timestamp, - bounce_type: bounce_type, - bounce_subtype: bounce_subtype, - feedback_id: feedback_id, - reporting_mta: reporting_mta) - end - - def timestamp - @timestamp ||= DateTime.parse @notification.message["bounce"]["timestamp"] - end - - def bounce_type - @bounce_type ||= @notification.message["bounce"]["bounceType"] - end - - def bounce_subtype - @bounce_subtype ||= @notification.message["bounce"]["bounceSubType"] - end - - def reporting_mta - @reporting_mta ||= @notification.message["bounce"]["reportingMTA"] - end - - def bounced_recipients - @bounced_recipients ||= @notification.message["bounce"]["bouncedRecipients"] - end - - def feedback_id - @feedback_id ||= @notification.message["bounce"]["feedbackId"] - end - end -end diff --git a/lib/notification_handlers/click_handler.rb b/lib/notification_handlers/click_handler.rb deleted file mode 100644 index d02f25d..0000000 --- a/lib/notification_handlers/click_handler.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -module NotificationHandlers - class ClickHandler < BaseNotificationHandler - def handle - message = Message.find_by_tracking_id @notification.tracking_id - message.activities << MessageActivity.new(activity_type: :clicked, - notification_timestamp: timestamp, - ip_address: ip_address, - user_agent: user_agent, - link_url: link) - message.save - end - - private - - def timestamp - @timestamp ||= DateTime.parse @notification.message["click"]["timestamp"] - end - - def user_agent - @user_agent ||= @notification.message["click"]["userAgent"] - end - - def ip_address - @ip_address ||= @notification.message["click"]["ipAddress"] - end - - def link - @link ||= @notification.message["click"]["link"] - end - end -end diff --git a/lib/notification_handlers/complaint_handler.rb b/lib/notification_handlers/complaint_handler.rb deleted file mode 100644 index 542fa5e..0000000 --- a/lib/notification_handlers/complaint_handler.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true - -module NotificationHandlers - class ComplaintHandler < BaseNotificationHandler - def handle - new_callback.tap do |callback| - complaint_recipients.each do |complaint_recipient| - recipient = transaction.recipients.find_by_email(complaint_recipient["emailAddress"]).first - next if recipient.nil? - - callback.recipients << MessageActivityRecipient.new( - recipient: recipient - ) - end - - callback.save! - end - end - - private - - def new_callback - MessageActivity.new(activity_type: :complaint, - message: message, - notification_timestamp: timestamp, - complaint_type: complaint_type, - user_agent: user_agent, - complaint_arrival_date: arrival_date, - feedback_id: feedback_id) - end - - def timestamp - @timestamp ||= DateTime.parse @notification.message["complaint"]["timestamp"] - end - - def arrival_date - @arrival_date ||= DateTime.parse @notification.message["complaint"]["arrivalDate"] - end - - def user_agent - @user_agent ||= @notification.message["complaint"]["userAgent"] - end - - def complaint_type - @complaint_type ||= @notification.message["complaint"]["complaintFeedbackType"] - end - - def feedback_id - @feedback_id ||= @notification.message["complaint"]["feedbackId"] - end - - def complaint_recipients - @complaint_recipients ||= @notification.message["complaint"]["complainedRecipients"] - end - end -end diff --git a/lib/notification_handlers/delivered_handler.rb b/lib/notification_handlers/delivered_handler.rb deleted file mode 100644 index 8603675..0000000 --- a/lib/notification_handlers/delivered_handler.rb +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: true - -module NotificationHandlers - class DeliveredHandler < BaseNotificationHandler - def handle - recipients.each do |recipient| - create_activity recipient - end - - true - end - - private - - def create_activity(email) - recipient = message.recipients.where("email LIKE ?", "%#{email}%").first! - recipient.delivered_at = timestamp - recipient.activities << MessageActivity.new(activity_type: :delivered, - message: message, - notification_timestamp: timestamp, - smtp_response: smtp_response, - reporting_mta: reporting_mta) - recipient.save - end - - def timestamp - @timestamp ||= DateTime.parse @notification.message["delivery"]["timestamp"] - end - - def smtp_response - @smtp_response ||= @notification.message["delivery"]["smtpResponse"] - end - - def reporting_mta - @reporting_mta ||= @notification.message["delivery"]["reportingMTA"] - end - - def recipients - @recipients ||= @notification.message["delivery"]["recipients"] - end - end -end diff --git a/lib/notification_handlers/ignored_handler.rb b/lib/notification_handlers/ignored_handler.rb deleted file mode 100644 index 3a67f3d..0000000 --- a/lib/notification_handlers/ignored_handler.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -module NotificationHandlers - class IgnoredHandler < BaseNotificationHandler - def handle - Sentry.capture_exception("Ignored EmailCallback of type #{@notification.type}", level: :info) - - true - end - end -end diff --git a/lib/notification_handlers/opened_handler.rb b/lib/notification_handlers/opened_handler.rb deleted file mode 100644 index e5df76d..0000000 --- a/lib/notification_handlers/opened_handler.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -module NotificationHandlers - class OpenedHandler < BaseNotificationHandler - def handle - message.activities << MessageActivity.new(activity_type: :opened, - notification_timestamp: timestamp, - ip_address: ip_address, - user_agent: user_agent) - message.save - end - - private - - def timestamp - @timestamp ||= DateTime.parse @notification.message["open"]["timestamp"] - end - - def user_agent - @user_agent ||= @notification.message["open"]["userAgent"] - end - - def ip_address - @ip_address ||= @notification.message["open"]["ipAddress"] - end - end -end diff --git a/lib/notification_handlers/reject_handler.rb b/lib/notification_handlers/reject_handler.rb deleted file mode 100644 index a972c0e..0000000 --- a/lib/notification_handlers/reject_handler.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -module NotificationHandlers - class RejectHandler < BaseNotificationHandler - def handle - MessageActivity.create!(message: message, - callback_type: :reject, - callback_timestamp: Time.zone.now, - reject_reason: reject_reason) - end - - private - - def reject_reason - @reject_reason ||= @notification.message["reject"]["reason"] - end - end -end diff --git a/lib/notification_handlers/send_handler.rb b/lib/notification_handlers/send_handler.rb deleted file mode 100644 index d0255fc..0000000 --- a/lib/notification_handlers/send_handler.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -module NotificationHandlers - class SendHandler < BaseNotificationHandler - def handle - message.activities << MessageActivity.new(activity_type: :sent, - notification_timestamp: timestamp) - message.save - end - - private - - def timestamp - @timestamp ||= DateTime.parse @notification.message["mail"]["timestamp"] - end - end -end diff --git a/lib/notification_handlers/subscribe_handler.rb b/lib/notification_handlers/subscribe_handler.rb deleted file mode 100644 index 4e2422a..0000000 --- a/lib/notification_handlers/subscribe_handler.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -module NotificationHandlers - class SubscribeHandler < BaseNotificationHandler - def handle - Net::HTTP.get_response(subscribe_uri).is_a? Net::HTTPSuccess - end - - private - - def subscribe_uri - @subscribe_uri ||= URI @notification.subscribe_url - end - end -end diff --git a/lib/notification_processor.rb b/lib/notification_processor.rb deleted file mode 100644 index db9ed30..0000000 --- a/lib/notification_processor.rb +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: true - -# Processes notifications recived from AWS -class NotificationProcessor - UnknownNotificationError = Class.new(StandardError) - HANDLER_MAPPINGS = { - "SubscriptionConfirmation" => "SubscribeHandler", - "SubscriptionCancellation" => "IgnoredHandler", - "SubscriptionValidation" => "IgnoredHandler", - "Send" => "SendHandler", - "Bounce" => "BounceHandler", - "Delivery" => "DeliveredHandler", - "Click" => "ClickHandler", - "Open" => "OpenedHandler", - "Complaint" => "ComplaintHandler", - "Reject" => "RejectHandler", - "RenderingFailure" => "RenderingFailureHandler" - }.freeze - - def initialize(raw_data) - @notification = AwsNotification.new raw_data - raise UnknownNotificationError unless valid_notification? - end - - def process - handler.handle - end - - private - - def handler - @handler ||= "NotificationHandlers::#{handler_name}".constantize.new(@notification) - end - - def handler_name - HANDLER_MAPPINGS[@notification.type] - end - - def valid_notification? - HANDLER_MAPPINGS.key?(@notification.type) - end -end diff --git a/lib/plain_text.rb b/lib/plain_text.rb deleted file mode 100644 index 7651751..0000000 --- a/lib/plain_text.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -class PlainText - def initialize(html_input) - @html_input = html_input - end - - def self.from_html(html_input) - new(html_input).value - end - - def value - response = Mailchimp::ApiClient.html_to_text(@html_input) - if response.success? - response.body - else - parsed_from_nokogiri - end - end - - private - - def parsed_from_nokogiri - body_parts = [] - Nokogiri::HTML(@html_input).traverse do |node| - if node.text? && !(content = node.content ? node.content.strip : nil).blank? - body_parts << content - elsif node.name == "a" && (href = node.attr("href")) && href.match(/^https?:/) - body_parts << href - end - end - - body_parts.uniq.join("\n") - end -end diff --git a/lib/redis_config_builder.rb b/lib/redis_config_builder.rb deleted file mode 100644 index 0657443..0000000 --- a/lib/redis_config_builder.rb +++ /dev/null @@ -1,23 +0,0 @@ -class RedisConfigBuilder - def self.build(namespace = nil) - new.build(namespace) - end - - def build(namespace = nil) - default_config.tap do |config| - config[:namespace] = "#{config[:namespace]}-#{namespace}" if namespace.present? - config[:ssl_params] = {verify_mode: OpenSSL::SSL::VERIFY_NONE} if ENV.fetch("REDIS_SSL", "0") == "1" - end - end - - private - - def default_config - { - url: ENV["REDIS_URL"], - namespace: ENV["REDIS_NAMESPACE"], - network_timeout: 3, - driver: :ruby - } - end -end diff --git a/lib/sidebar_helpers.rb b/lib/sidebar_helpers.rb deleted file mode 100644 index 4c42a4d..0000000 --- a/lib/sidebar_helpers.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -# Helpers with the sidebar -module SidebarHelpers - def profile_link - {href: edit_user_registration_path} - end - - def sidebar_link(link, active_if) - {class: ("active" if active_if), href: link} - end - - def clients_controller? - controller.instance_of?(ClientsController) || controller.instance_of?(SubscribersController) - end - - def messages_controller? - controller.instance_of?(MessagesController) - end - - def subscribers_controller? - controller.instance_of?(SubscribersController) - end - - def subscriptions_controller? - controller.instance_of?(SubscriptionsController) - end - - def home_action?(action) - controller.instance_of?(HomeController) && controller.action_name == action - end - - private - - def disable_item - {href: "#", - onclick: "'alert('#{t("feature_un")}');'"} - end -end diff --git a/lib/tasks/db_exists.rake b/lib/tasks/db_exists.rake deleted file mode 100644 index 753118e..0000000 --- a/lib/tasks/db_exists.rake +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -namespace :db do - desc "Checks to see if the database exists" - task :exists do - Rake::Task["environment"].invoke - ActiveRecord::Base.connection - rescue - puts "Does not exist" - exit 1 - else - puts "Already exists" - exit 0 - end -end diff --git a/package.json b/package.json deleted file mode 100644 index cc087e5..0000000 --- a/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "hermes", - "version": "0.5.1", - "repository": "https://gitlab.com/mythcoders/hermes", - "author": "Justin Adkins ", - "license": "GNU AGPLv3", - "private": true, - "dependencies": { - "@hotwired/turbo-rails": "^7.0.0-rc.1", - "@rails/actiontext": "^6.0.3-6", - "@rails/activestorage": "^6.0.3-4", - "@rails/ujs": "~6.0", - "@rails/webpacker": "^5.2.1", - "@sentry/browser": "^5.29.2", - "autoprefixer": "^10.3.1", - "halfmoon": "^1.1.1", - "postcss": "^8.3.6", - "postcss-loader": "^3.0.0", - "stimulus": "^2.0.0", - "trix": "^1.2.0" - }, - "devDependencies": { - "webpack-dev-server": "^3.11.2" - } -} diff --git a/postcss.config.js b/postcss.config.js deleted file mode 100644 index aa5998a..0000000 --- a/postcss.config.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = { - plugins: [ - require('postcss-import'), - require('postcss-flexbugs-fixes'), - require('postcss-preset-env')({ - autoprefixer: { - flexbox: 'no-2009' - }, - stage: 3 - }) - ] -} diff --git a/public/404.html b/public/404.html deleted file mode 100644 index 2be3af2..0000000 --- a/public/404.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - The page you were looking for doesn't exist (404) - - - - - - -
-
-

The page you were looking for doesn't exist.

-

You may have mistyped the address or the page may have moved.

-
-

If you are the application owner check the logs for more information.

-
- - diff --git a/public/422.html b/public/422.html deleted file mode 100644 index c08eac0..0000000 --- a/public/422.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - The change you wanted was rejected (422) - - - - - - -
-
-

The change you wanted was rejected.

-

Maybe you tried to change something you didn't have access to.

-
-

If you are the application owner check the logs for more information.

-
- - diff --git a/public/500.html b/public/500.html deleted file mode 100644 index 78a030a..0000000 --- a/public/500.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - We're sorry, but something went wrong (500) - - - - - - -
-
-

We're sorry, but something went wrong.

-
-

If you are the application owner check the logs for more information.

-
- - diff --git a/public/apple-touch-icon-precomposed.png b/public/apple-touch-icon-precomposed.png deleted file mode 100644 index e69de29..0000000 diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png deleted file mode 100644 index e69de29..0000000 diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index e69de29..0000000 diff --git a/public/img/masks/avatar-group-hover-last.svg b/public/img/masks/avatar-group-hover-last.svg deleted file mode 100644 index 22abb06..0000000 --- a/public/img/masks/avatar-group-hover-last.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/public/img/masks/avatar-group-hover.svg b/public/img/masks/avatar-group-hover.svg deleted file mode 100644 index ed5bd16..0000000 --- a/public/img/masks/avatar-group-hover.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/public/img/masks/avatar-group.svg b/public/img/masks/avatar-group.svg deleted file mode 100644 index d67e8d3..0000000 --- a/public/img/masks/avatar-group.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/public/img/masks/avatar-status.svg b/public/img/masks/avatar-status.svg deleted file mode 100644 index fca5423..0000000 --- a/public/img/masks/avatar-status.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/public/img/masks/icon-status.svg b/public/img/masks/icon-status.svg deleted file mode 100644 index 0b880fb..0000000 --- a/public/img/masks/icon-status.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/public/logo.png b/public/logo.png deleted file mode 100644 index d5cb3ec0761098e5f055cf5f4fa6346397e24308..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 696 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDB3?!H8JlO)ISkfJR9T^xl_H+M9WCijSl0AZa z85pY67#JE_7#My5g&JNkFq8r{zDi(Vu$sZZAYL$MSD+10LNUN6#1*8Vq2a)R13>Ek z|NjgPK!N`t0!V>~hM*L)P$11%666=m;PC858i^mS!_#3msw zXz=ik%?6-!yQhm|h{fsL%Nw%}8wju^{N`Pi(DXv>ChK}$lj;_!UE3Z6?YVaC!N!u4 z&!+Iq^j7eHknm@Ut*3hQs@e%p|9^VkqU=6Vc9Fe7d7#0^yIn3V%QJs@{F!q^=V43! zk=YMg^|h6@*ra4KKIUw3o7bJoYxLGr#cN^7)6%B(fhCJG+;{xzTl74+4S}TF3=0|jFK9%wBuWK6WB9s7#dFDy9|6<8#jJLD^km24*XlQ{ zf823eTw?#Uc~$p0oz6-I^Q9jm3bPXW1I)axZriwV!||uhLB1CX3W9wv>mJ-4bU2~m zj5J#Z4+EF^Wd)<0HB)mPoH(ycMDg>( znp=Wdd`}P9tdZI0|F5}j-_CQ4RmJ%`FC1ueS@v0gh2t5+T6TpQ!nbaRH>A&8V{}gS zS<5y)7d1wS!i2m-GqWEiv1xE8wE8<7|L%60CHP&-*&-3M^J_P>-r@|Y5ikG% diff --git a/public/robots.txt b/public/robots.txt deleted file mode 100644 index c6742d8..0000000 --- a/public/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-Agent: * -Disallow: / diff --git a/scripts/app b/scripts/app deleted file mode 100755 index 0c896a4..0000000 --- a/scripts/app +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -echo '==> Booting Hermes...' - -if [ "$2" == "setup" ]; then - echo "==> Verifying database..." - ./bin/rails db:exists && ./bin/rails db:migrate VERBOSE=true || ./bin/rails db:setup VERBOSE=true -fi - -if [ "$1" == "start" ]; then - if [ -f "${APP_HOME}/tmp/pids/server.pid" ]; then - echo "==> Flushing server.pid" - rm -rf ${APP_HOME}/tmp/health_checks/app - rm -rf ${APP_HOME}/tmp/pids/server.pid - fi - - echo "==> Launching web server..." - mkdir -p ${APP_HOME}/tmp/health_checks && touch ${APP_HOME}/tmp/health_checks/app - ./bin/rails s -b 0.0.0.0 -p 5000 -fi diff --git a/scripts/bootstrap b/scripts/bootstrap deleted file mode 100644 index 5dff181..0000000 --- a/scripts/bootstrap +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -# script/bootstrap: Resolve all dependencies that the application requires to -# run. - -set -e - -cd "$(dirname "$0")/.." - -if [ -f "Gemfile" ]; then - echo "==> Installing gem dependencies…" - bundle check --path vendor/gems >/dev/null 2>&1 || { - bundle install --path vendor/gems --quiet --without production - } -fi \ No newline at end of file diff --git a/scripts/cibuild b/scripts/cibuild deleted file mode 100755 index 3e349b1..0000000 --- a/scripts/cibuild +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -# script/cibuild: Run stuff - -if [ "$1" = "audit" ]; then - echo "==> Running bundler audit…" - bundle audit check --update -elif [ "$1" = "brakeman" ]; then - echo "==> Running brakeman…" - brakeman -q -w2 -elif [ "$1" = "linter" ]; then - echo "==> Running linter…" - bundle exec standardrb --format progress --parallel -elif [ "$1" = "rspec" ]; then - echo "==> Running rspec…" - bundle exec rspec --format documentation -else - echo "Unknown arg $1. Usage: $0 {audit|linter|rspec}" - exit 1 -fi \ No newline at end of file diff --git a/scripts/console b/scripts/console deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/server b/scripts/server deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/setup b/scripts/setup deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/test b/scripts/test deleted file mode 100755 index c58df7e..0000000 --- a/scripts/test +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -# script/test: Run test suite for application. Optionally pass in a path to an -# individual test file to run a single test. - - -set -e - -cd "$(dirname "$0")/.." - -[ -z "$DEBUG" ] || set -x - -RACK_ROOT="$(cd "$(dirname "$0")"/.. && pwd)" -export RACK_ROOT - -if [ "$RAILS_ENV" = "test" ] || [ "$RACK_ENV" = "test" ]; then - # if executed and the environment is already set to `test`, then we want a - # clean from scratch application. This almost always means a ci environment, - # since we set the environment to `test` directly in `script/cibuild`. - script/setup -else - # if the environment isn't set to `test`, set it to `test` and update the - # application to ensure all dependencies are met as well as any other things - # that need to be up to date, like db migrations. The environment not having - # already been set to `test` almost always means this is being called on its - # own from a `development` environment. - export RAILS_ENV="test" RACK_ENV="test" - - script/update -fi - -echo "==> Running tests…" - -if [ -n "$1" ]; then - # pass arguments to test call. This is useful for calling a single test. - bundle exec rspec "$1" -else - bundle exec rspec -fi diff --git a/scripts/update b/scripts/update deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/webpack b/scripts/webpack deleted file mode 100755 index 3c15c08..0000000 --- a/scripts/webpack +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -echo 'Starting Hermes' -echo 'Starting Webpack...' - -rm -rf ${APP_HOME}/public/packs -${APP_HOME}/bin/webpack-dev-server diff --git a/scripts/worker b/scripts/worker deleted file mode 100755 index 882827d..0000000 --- a/scripts/worker +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# kill -3 Wait for child to finish processing then exit - -if [ "$1" == "start" ]; then - echo "==> Booting Hermes..." - - if [ -f "${APP_HOME}/tmp/pids/sidekiq.pid" ]; then - echo "==> Flushing worker pid" - rm -rf ${APP_HOME}/tmp/pids/sidekiq.pid - fi - - echo "==> Starting Hermes workers..." - mkdir -p ${APP_HOME}/tmp/health_checks && touch ${APP_HOME}/tmp/health_checks/worker - bundle exec sidekiq -elif [ "$1" == "stop" ]; then - echo "==> Stopping Hermes workers..." - for f in tmp/pids/sidekiq*.pid; do - echo "==> worker $f..." - bundle exec sidekiqctl stop $f; - done - - rm -rf ${APP_HOME}/tmp/health_checks/worker - echo "==> Stopped!" -else - echo "Unknown arg $1. Usage: $0 {start|stop}" - exit 1 -fi \ No newline at end of file diff --git a/spec/factories/clients.rb b/spec/factories/clients.rb deleted file mode 100644 index d7227c7..0000000 --- a/spec/factories/clients.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -FactoryBot.define do - factory :client do - name { Faker::Movies::LordOfTheRings.location } - owner { Faker::Movies::LordOfTheRings.character } - reroute_email { Faker::Internet.email } - api_secret { SecureRandom.urlsafe_base64(64) } - api_key { SecureRandom.urlsafe_base64(64) } - is_active { true } - are_emails_sent { false } - - trait :inactive do - is_active { false } - end - - trait :allowed_to_send do - are_emails_sent { true } - end - end -end diff --git a/spec/factories/messages.rb b/spec/factories/messages.rb deleted file mode 100644 index d3c2dc8..0000000 --- a/spec/factories/messages.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -FactoryBot.define do - factory :message do - client { create(:client) } - sender { Faker::Internet.email } - subject { Faker::Cannabis.buzzword } - environment { "rspec" } - tracking_id { SecureRandom.uuid } - end -end diff --git a/spec/factories/users.rb b/spec/factories/users.rb deleted file mode 100644 index 7e87054..0000000 --- a/spec/factories/users.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -FactoryBot.define do - factory :user do - email { "#{Faker::Lorem.characters(number: 5)}@mythcoders.com" } - password { Faker::Lorem.characters(number: 15) } - name { Faker::Movies::HarryPotter.character } - end -end diff --git a/spec/fixtures/notifications/click.json b/spec/fixtures/notifications/click.json deleted file mode 100644 index 92367bf..0000000 --- a/spec/fixtures/notifications/click.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Type" : "Notification", - "MessageId" : "2d66c28b-5f55-5961-9e2a-943b94c95d89", - "TopicArn" : "arn:aws:sns:us-east-1:059584495509:Hermes", - "Subject" : "Amazon SES Email Event Notification", - "Message" : "{\"eventType\":\"Click\",\"mail\":{\"timestamp\":\"2020-02-02T09:56:13.738Z\",\"source\":\"hermes@mythcoders.com\",\"sendingAccountId\":\"059584495509\",\"messageId\":\"010001700554452a-39c1ff4d-fde4-4009-8378-ec273b747bb6-000000\",\"destination\":[\"justin.adkins@mythcoders.com\"],\"headersTruncated\":false,\"headers\":[{\"name\":\"Received\",\"value\":\"from mythcoders.com ([159.65.226.130]) by email-smtp.amazonaws.com with SMTP (SimpleEmailService-d-Q0ARBQ652) id lZVAd37ZgKLRe7OqPtMw for justin.adkins@mythcoders.com; Sun, 02 Feb 2020 09:56:13 +0000 (UTC)\"},{\"name\":\"Date\",\"value\":\"Sun, 02 Feb 2020 04:56:13 -0500\"},{\"name\":\"From\",\"value\":\"Hermes \"},{\"name\":\"Reply-To\",\"value\":\"MythCoders Support \"},{\"name\":\"To\",\"value\":\"Justin Adkins \"},{\"name\":\"Message-ID\",\"value\":\"<5e369cbd6a47c_72b0c0831b318189a8@review-delivery-r-emv0cm-sidekiq-7f95f4b5d-8srw6.mail>\"},{\"name\":\"Subject\",\"value\":\"[REROUTED] Eos odio est animi quisquam.\"},{\"name\":\"Mime-Version\",\"value\":\"1.0\"},{\"name\":\"Content-Type\",\"value\":\"text/html; charset=UTF-8\"},{\"name\":\"Content-Transfer-Encoding\",\"value\":\"7bit\"},{\"name\":\"X-Hermes-ID\",\"value\":\"ff20c991-fe2b-4f6c-ba3d-48a7c0fec236\"},{\"name\":\"X-SES-CONFIGURATION-SET\",\"value\":\"Hermes\"}],\"commonHeaders\":{\"from\":[\"Hermes \"],\"replyTo\":[\"MythCoders Support \"],\"date\":\"Sun, 02 Feb 2020 04:56:13 -0500\",\"to\":[\"Justin Adkins \"],\"messageId\":\"010001700554452a-39c1ff4d-fde4-4009-8378-ec273b747bb6-000000\",\"subject\":\"[REROUTED] Eos odio est animi quisquam.\"},\"tags\":{\"ses:operation\":[\"SendSmtpEmail\"],\"ses:configuration-set\":[\"Hermes\"],\"ses:source-ip\":[\"159.65.226.130\"],\"ses:from-domain\":[\"mythcoders.com\"],\"ses:caller-identity\":[\"mc-hermes-app\"]}},\"click\":{\"timestamp\":\"2020-02-02T13:06:36.667Z\",\"ipAddress\":\"75.118.11.196\",\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15\",\"link\":\"https://www.mythcoders.com?answer=love\",\"linkTags\":null}}\n", - "Timestamp" : "2020-02-02T13:06:36.734Z", - "SignatureVersion" : "1", - "Signature" : "YY9LjkAvYY9xKPrHQ9w+cjWc7rfqao7/esJD0Cj1viP1/huuqYgzML9xIl6EqFvjJpoxoZAcjjShROU+A0UXpS0rWB0xfYTEqrqYPYczGJ38iEqaFwhl9tYgrwj64+ukU7NL81ASc8b984K0MpdsM/Al1un3iRAV0KaffuHNWMbPWgiYTP6fe/cO51MIbuHsroVvGaB/xqpRdQB3rwyuSPdQvaeUs7SEHWgq748kj5cgr8szBq/m0llp6Pwdnk5BcZN79ckL3JgTDDA+rHT/P2Iui/QhOvdHBQwp7PAKHmFpOAdI/c/SYojHCe60UzcqHAa6iqXBZ0WNcSp4JVSASg==", - "SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-a86cb10b4e1f29c941702d737128f7b6.pem", - "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:059584495509:Hermes:228655dd-6da0-4756-8b26-9c3de38b6a46" -} diff --git a/spec/fixtures/notifications/delivery.json b/spec/fixtures/notifications/delivery.json deleted file mode 100644 index 50cbe07..0000000 --- a/spec/fixtures/notifications/delivery.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Type": "Notification", - "MessageId": "ca9e2f2f-9e54-5dd0-9725-799f015d1614", - "TopicArn": "arn:aws:sns:us-east-1:059584495509:Hermes", - "Subject": "Amazon SES Email Event Notification", - "Message": "{\"eventType\":\"Open\",\"mail\":{\"timestamp\":\"2020-02-02T09:56:13.738Z\",\"source\":\"hermes@mythcoders.com\",\"sendingAccountId\":\"059584495509\",\"messageId\":\"010001700554452a-39c1ff4d-fde4-4009-8378-ec273b747bb6-000000\",\"destination\":[\"justin.adkins@mythcoders.com\"],\"headersTruncated\":false,\"headers\":[{\"name\":\"Received\",\"value\":\"from mythcoders.com ([159.65.226.130]) by email-smtp.amazonaws.com with SMTP (SimpleEmailService-d-Q0ARBQ652) id lZVAd37ZgKLRe7OqPtMw for justin.adkins@mythcoders.com; Sun, 02 Feb 2020 09:56:13 +0000 (UTC)\"},{\"name\":\"Date\",\"value\":\"Sun, 02 Feb 2020 04:56:13 -0500\"},{\"name\":\"From\",\"value\":\"Hermes \"},{\"name\":\"Reply-To\",\"value\":\"MythCoders Support \"},{\"name\":\"To\",\"value\":\"Justin Adkins \"},{\"name\":\"Message-ID\",\"value\":\"<5e369cbd6a47c_72b0c0831b318189a8@review-delivery-r-emv0cm-sidekiq-7f95f4b5d-8srw6.mail>\"},{\"name\":\"Subject\",\"value\":\"[REROUTED] Eos odio est animi quisquam.\"},{\"name\":\"Mime-Version\",\"value\":\"1.0\"},{\"name\":\"Content-Type\",\"value\":\"text/html; charset=UTF-8\"},{\"name\":\"Content-Transfer-Encoding\",\"value\":\"7bit\"},{\"name\":\"X-Hermes-ID\",\"value\":\"ff20c991-fe2b-4f6c-ba3d-48a7c0fec236\"},{\"name\":\"X-SES-CONFIGURATION-SET\",\"value\":\"Hermes\"}],\"commonHeaders\":{\"from\":[\"Hermes \"],\"replyTo\":[\"MythCoders Support \"],\"date\":\"Sun, 02 Feb 2020 04:56:13 -0500\",\"to\":[\"Justin Adkins \"],\"messageId\":\"010001700554452a-39c1ff4d-fde4-4009-8378-ec273b747bb6-000000\",\"subject\":\"[REROUTED] Eos odio est animi quisquam.\"},\"tags\":{\"ses:operation\":[\"SendSmtpEmail\"],\"ses:configuration-set\":[\"Hermes\"],\"ses:source-ip\":[\"159.65.226.130\"],\"ses:from-domain\":[\"mythcoders.com\"],\"ses:caller-identity\":[\"mc-hermes-app\"]}},\"open\":{\"timestamp\":\"2020-02-02T09:56:25.271Z\",\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko)\",\"ipAddress\":\"75.118.11.196\"}}\n", - "Timestamp": "2020-02-02T09:56:25.368Z", - "SignatureVersion": "1", - "Signature": "value", - "SigningCertURL": "value", - "UnsubscribeURL": "value" -} diff --git a/spec/fixtures/notifications/open.json b/spec/fixtures/notifications/open.json deleted file mode 100644 index 50cbe07..0000000 --- a/spec/fixtures/notifications/open.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Type": "Notification", - "MessageId": "ca9e2f2f-9e54-5dd0-9725-799f015d1614", - "TopicArn": "arn:aws:sns:us-east-1:059584495509:Hermes", - "Subject": "Amazon SES Email Event Notification", - "Message": "{\"eventType\":\"Open\",\"mail\":{\"timestamp\":\"2020-02-02T09:56:13.738Z\",\"source\":\"hermes@mythcoders.com\",\"sendingAccountId\":\"059584495509\",\"messageId\":\"010001700554452a-39c1ff4d-fde4-4009-8378-ec273b747bb6-000000\",\"destination\":[\"justin.adkins@mythcoders.com\"],\"headersTruncated\":false,\"headers\":[{\"name\":\"Received\",\"value\":\"from mythcoders.com ([159.65.226.130]) by email-smtp.amazonaws.com with SMTP (SimpleEmailService-d-Q0ARBQ652) id lZVAd37ZgKLRe7OqPtMw for justin.adkins@mythcoders.com; Sun, 02 Feb 2020 09:56:13 +0000 (UTC)\"},{\"name\":\"Date\",\"value\":\"Sun, 02 Feb 2020 04:56:13 -0500\"},{\"name\":\"From\",\"value\":\"Hermes \"},{\"name\":\"Reply-To\",\"value\":\"MythCoders Support \"},{\"name\":\"To\",\"value\":\"Justin Adkins \"},{\"name\":\"Message-ID\",\"value\":\"<5e369cbd6a47c_72b0c0831b318189a8@review-delivery-r-emv0cm-sidekiq-7f95f4b5d-8srw6.mail>\"},{\"name\":\"Subject\",\"value\":\"[REROUTED] Eos odio est animi quisquam.\"},{\"name\":\"Mime-Version\",\"value\":\"1.0\"},{\"name\":\"Content-Type\",\"value\":\"text/html; charset=UTF-8\"},{\"name\":\"Content-Transfer-Encoding\",\"value\":\"7bit\"},{\"name\":\"X-Hermes-ID\",\"value\":\"ff20c991-fe2b-4f6c-ba3d-48a7c0fec236\"},{\"name\":\"X-SES-CONFIGURATION-SET\",\"value\":\"Hermes\"}],\"commonHeaders\":{\"from\":[\"Hermes \"],\"replyTo\":[\"MythCoders Support \"],\"date\":\"Sun, 02 Feb 2020 04:56:13 -0500\",\"to\":[\"Justin Adkins \"],\"messageId\":\"010001700554452a-39c1ff4d-fde4-4009-8378-ec273b747bb6-000000\",\"subject\":\"[REROUTED] Eos odio est animi quisquam.\"},\"tags\":{\"ses:operation\":[\"SendSmtpEmail\"],\"ses:configuration-set\":[\"Hermes\"],\"ses:source-ip\":[\"159.65.226.130\"],\"ses:from-domain\":[\"mythcoders.com\"],\"ses:caller-identity\":[\"mc-hermes-app\"]}},\"open\":{\"timestamp\":\"2020-02-02T09:56:25.271Z\",\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko)\",\"ipAddress\":\"75.118.11.196\"}}\n", - "Timestamp": "2020-02-02T09:56:25.368Z", - "SignatureVersion": "1", - "Signature": "value", - "SigningCertURL": "value", - "UnsubscribeURL": "value" -} diff --git a/spec/fixtures/notifications/send.json b/spec/fixtures/notifications/send.json deleted file mode 100644 index 7ba85fd..0000000 --- a/spec/fixtures/notifications/send.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Type": "Notification", - "MessageId": "9b288433-be70-582c-ac33-d283208ec81a", - "TopicArn": "arn:aws:sns:us-east-1:059584495509:Hermes", - "Subject": "Amazon SES Email Event Notification", - "Message": "{\"eventType\":\"Send\",\"mail\":{\"timestamp\":\"2020-02-02T09:56:13.738Z\",\"source\":\"hermes@mythcoders.com\",\"sourceArn\":\"arn:aws:ses:us-east-1:059584495509:identity/mythcoders.com\",\"sendingAccountId\":\"059584495509\",\"messageId\":\"010001700554452a-39c1ff4d-fde4-4009-8378-ec273b747bb6-000000\",\"destination\":[\"justin.adkins@mythcoders.com\"],\"headersTruncated\":false,\"headers\":[{\"name\":\"Received\",\"value\":\"from mythcoders.com ([159.65.226.130]) by email-smtp.amazonaws.com with SMTP (SimpleEmailService-d-Q0ARBQ652) id lZVAd37ZgKLRe7OqPtMw for justin.adkins@mythcoders.com; Sun, 02 Feb 2020 09:56:13 +0000 (UTC)\"},{\"name\":\"Date\",\"value\":\"Sun, 02 Feb 2020 04:56:13 -0500\"},{\"name\":\"From\",\"value\":\"Hermes \"},{\"name\":\"Reply-To\",\"value\":\"MythCoders Support \"},{\"name\":\"To\",\"value\":\"Justin Adkins \"},{\"name\":\"Message-ID\",\"value\":\"<5e369cbd6a47c_72b0c0831b318189a8@review-delivery-r-emv0cm-sidekiq-7f95f4b5d-8srw6.mail>\"},{\"name\":\"Subject\",\"value\":\"[REROUTED] Eos odio est animi quisquam.\"},{\"name\":\"Mime-Version\",\"value\":\"1.0\"},{\"name\":\"Content-Type\",\"value\":\"text/html; charset=UTF-8\"},{\"name\":\"Content-Transfer-Encoding\",\"value\":\"7bit\"},{\"name\":\"X-Hermes-ID\",\"value\":\"ff20c991-fe2b-4f6c-ba3d-48a7c0fec236\"},{\"name\":\"X-SES-CONFIGURATION-SET\",\"value\":\"Hermes\"}],\"commonHeaders\":{\"from\":[\"Hermes \"],\"replyTo\":[\"MythCoders Support \"],\"date\":\"Sun, 02 Feb 2020 04:56:13 -0500\",\"to\":[\"Justin Adkins \"],\"messageId\":\"010001700554452a-39c1ff4d-fde4-4009-8378-ec273b747bb6-000000\",\"subject\":\"[REROUTED] Eos odio est animi quisquam.\"},\"tags\":{\"ses:operation\":[\"SendSmtpEmail\"],\"ses:configuration-set\":[\"Hermes\"],\"ses:source-ip\":[\"159.65.226.130\"],\"ses:from-domain\":[\"mythcoders.com\"],\"ses:caller-identity\":[\"mc-hermes-app\"]}},\"send\":{}}\n", - "Timestamp": "2020-02-02T09:56:14.002Z", - "SignatureVersion": "1", - "Signature": "value", - "SigningCertURL": "value", - "UnsubscribeURL": "value" -} diff --git a/spec/initializers/shoulda_matchers.rb b/spec/initializers/shoulda_matchers.rb deleted file mode 100644 index edcf9dd..0000000 --- a/spec/initializers/shoulda_matchers.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -Shoulda::Matchers.configure do |config| - config.integrate do |with| - with.test_framework :rspec - with.library :rails - end -end diff --git a/spec/lib/aws_notification_spec.rb b/spec/lib/aws_notification_spec.rb deleted file mode 100644 index de238e9..0000000 --- a/spec/lib/aws_notification_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -# RSpec.describe AwsNotification do -# xdescribe 'initialize' do -# let(:notification) { '' } -# -# context 'with unknown notification type' do -# let(:notification_type) { 'Dude' } -# -# it 'should raise UnknownNotificationError' do -# expect { subject.new(notification) }.to raise_error(UnknownNotificationError) -# end -# end -# -# context 'with known notification type' do -# let(:notification_type) { 'Send' } -# -# it 'should call to a notification handler' do -# end -# end -# end -# end diff --git a/spec/lib/notification_processor_spec.rb b/spec/lib/notification_processor_spec.rb deleted file mode 100644 index 87dce7a..0000000 --- a/spec/lib/notification_processor_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -# RSpec.describe NotificationProcessor do -# xdescribe 'initialize' do -# let(:notification) { '' } -# -# context 'with unknown notification type' do -# let(:notification_type) { 'Dude' } -# -# it 'should raise UnknownNotificationError' do -# expect { subject.new(notification) }.to raise_error(UnknownNotificationError) -# end -# end -# -# context 'with known notification type' do -# let(:notification_type) { 'Send' } -# -# it 'should call to a notification handler' do -# end -# end -# end -# end diff --git a/spec/mailers/api_mailer_spec.rb b/spec/mailers/api_mailer_spec.rb deleted file mode 100644 index 0356664..0000000 --- a/spec/mailers/api_mailer_spec.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -require "rails_helper" - -RSpec.describe ApiMailer, type: :mailer do -end diff --git a/spec/mailers/previews/api_mailer_preview.rb b/spec/mailers/previews/api_mailer_preview.rb deleted file mode 100644 index bd68a15..0000000 --- a/spec/mailers/previews/api_mailer_preview.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -# Preview all emails at http://localhost:3000/rails/mailers/api_mailer -class ApiMailerPreview < ActionMailer::Preview - # def send_message - # ApiMailer.send_message(request_params) - # end -end diff --git a/spec/models/client_spec.rb b/spec/models/client_spec.rb deleted file mode 100644 index 72c916f..0000000 --- a/spec/models/client_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -require "rails_helper" - -RSpec.describe Client, type: :model do - subject { create(:client) } - - it { should validate_presence_of(:name) } - it { should validate_presence_of(:owner) } - it { should validate_presence_of(:reroute_email) } - it { should validate_presence_of(:api_secret) } - it { should validate_presence_of(:api_key) } - it { should validate_length_of(:name).is_at_most(50) } - it { should validate_length_of(:owner).is_at_most(50) } - it { should validate_length_of(:reroute_email).is_at_most(60) } - it { should validate_length_of(:api_secret).is_at_most(128) } - it { should validate_length_of(:api_key).is_at_most(128) } - it { should validate_uniqueness_of(:name) } - it { should validate_uniqueness_of(:api_secret) } - it { should validate_uniqueness_of(:api_key) } -end diff --git a/spec/models/message_spec.rb b/spec/models/message_spec.rb deleted file mode 100644 index 41640ea..0000000 --- a/spec/models/message_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -require "rails_helper" - -RSpec.describe Message, type: :model do - it { should validate_presence_of(:sender) } - it { should validate_presence_of(:subject) } - it { should validate_presence_of(:client) } - it { should validate_presence_of(:environment) } - it { should validate_presence_of(:tracking_id) } - it { should belong_to(:client) } - - context "when being created" do - context "and client isn't active" do - let(:client) { create(:client, :inactive) } - subject { build(:message, client: client) } - - it "does not increase record count" do - expect { subject.save }.to change { Message.count }.by(0) - end - end - end - - # context 'after the record has been created' do - # subject { create(:message) } - # end -end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb deleted file mode 100644 index 681a579..0000000 --- a/spec/models/user_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -# frozen_string_literal: true - -require "rails_helper" - -RSpec.describe User, type: :model do - subject { create(:user) } - - describe "#create" do - it "only allow emails that belong to mythcoders" do - end - end - - describe "#email_domain" do - it "returns string when populated" do - subject.email = "harry@johnson.net" - expect(subject.email_domain).to eq("johnson.net") - end - - it "returns nil when no empty" do - subject.email = "" - expect(subject.email_domain).to eq(nil) - end - end -end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb deleted file mode 100644 index 4ed8dd7..0000000 --- a/spec/rails_helper.rb +++ /dev/null @@ -1,22 +0,0 @@ -# frozen_string_literal: true - -ENV["RAILS_ENV"] ||= "test" -require File.expand_path("../config/environment", __dir__) -abort("The Rails environment is running in production mode!") if Rails.env.production? -require "spec_helper" -require "rspec/rails" -require "devise" -require "sidekiq/testing" - -Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |f| require f } -Dir[Rails.root.join("spec/initializers/**/*.rb")].sort.each { |f| require f } - -ActiveRecord::Migration.maintain_test_schema! - -RSpec.configure do |config| - config.use_transactional_fixtures = true - config.infer_spec_type_from_file_location! - config.include Warden::Test::Helpers, type: :request - config.include Devise::Test::ControllerHelpers, type: :controller - config.include Devise::Test::ControllerHelpers, type: :view -end diff --git a/spec/requests/api_messages_spec.rb b/spec/requests/api_messages_spec.rb deleted file mode 100644 index 6c33a82..0000000 --- a/spec/requests/api_messages_spec.rb +++ /dev/null @@ -1,100 +0,0 @@ -# frozen_string_literal: true - -require "rails_helper" - -RSpec.describe "Messages API", type: :request do - shared_examples "forbidden request" do - it "responds with 403 status" do - post "/api/messages", params: request, headers: api_basic_auth(client) - expect(response.status).to eq(403) - end - end - - shared_examples "bad request" do - it "responds with 400 status" do - post "/api/messages", params: request, headers: api_basic_auth(client) - expect(response.status).to eq(400) - end - end - - shared_examples "successful request" do - it "responds with 201 status" do - post "/api/messages", params: request, headers: api_basic_auth(client) - expect(response.status).to eq(201) - end - - it "increases Message count" do - expect do - post "/api/messages", params: request, headers: api_basic_auth(client) - end.to change { Message.count }.by(1) - end - - it "queues MailSortJob" do - expect do - post "/api/messages", params: request, headers: api_basic_auth(client) - end.to have_enqueued_job MailSortJob - end - end - - describe "POST mail" do - context "when no client is supplied" do - it "responds with unauthorized" do - post "/api/messages" - expect(response.status).to eq(401) - end - end - - context "when client is not active" do - let!(:client) { create(:client, :inactive) } - it_behaves_like "forbidden request" - end - - context "when client is active" do - let(:client) { create(:client) } - let(:to) { [Faker::Internet.email] } - let(:subject) { Faker::Cannabis.buzzword } - let(:environment) { "test" } - let(:sender) { Faker::Internet.email } - let(:request) do - { - message: - { - to: to, - subject: subject, - environment: environment, - sender: sender - } - } - end - - context "request has bare minimum" do - it_behaves_like "successful request" - end - - context "request is empty" do - let(:request) { "" } - it_behaves_like "bad request" - end - - context "request does not include recipient" do - let(:to) { "" } - it_behaves_like "bad request" - end - - context "request does not include subject" do - let(:subject) { "" } - it_behaves_like "bad request" - end - - context "request does not include sender" do - let(:sender) { "" } - it_behaves_like "bad request" - end - - xcontext "request does not include environment" do - let(:environment) { "" } - it_behaves_like "bad request" - end - end - end -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb deleted file mode 100644 index ce4f870..0000000 --- a/spec/spec_helper.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -RSpec.configure do |config| - config.expect_with :rspec do |expectations| - expectations.include_chain_clauses_in_custom_matcher_descriptions = true - end - - config.mock_with :rspec do |mocks| - mocks.verify_partial_doubles = true - end - - config.filter_run_when_matching :focus - config.run_all_when_everything_filtered = true - - config.example_status_persistence_file_path = "spec/examples.txt" - - config.disable_monkey_patching! - - config.order = :random - Kernel.srand config.seed -end diff --git a/spec/support/factory_bot.rb b/spec/support/factory_bot.rb deleted file mode 100644 index 2e7665c..0000000 --- a/spec/support/factory_bot.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -RSpec.configure do |config| - config.include FactoryBot::Syntax::Methods -end diff --git a/spec/support/helper_methods.rb b/spec/support/helper_methods.rb deleted file mode 100644 index 7849855..0000000 --- a/spec/support/helper_methods.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -def random_string - SecureRandom.hex -end - -def random_integer - rand(1_000_000) -end - -def create_and_login_user - logout_user - current_user = FactoryBot.create(:user) - login_user current_user - current_user -end - -def login_user(user) - @request.env["devise.mapping"] = Devise.mappings[:user] - sign_in user -end - -def logout_user - sign_out :user -end - -def api_basic_auth(client) - { - HTTP_AUTHORIZATION: - ActionController::HttpAuthentication::Basic.encode_credentials(client.api_key, client.api_secret) - } -end diff --git a/vendor/hermes-gem b/vendor/hermes-gem deleted file mode 160000 index 7ec0743..0000000 --- a/vendor/hermes-gem +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7ec0743b0cd5f017beaff3a199632598dea4f39d diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index afd3f7b..0000000 --- a/yarn.lock +++ /dev/null @@ -1,7074 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" - integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== - dependencies: - "@babel/highlight" "^7.14.5" - -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.7", "@babel/compat-data@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" - integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== - -"@babel/core@^7.14.3": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.0.tgz#749e57c68778b73ad8082775561f67f5196aafa8" - integrity sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.15.0" - "@babel/helper-compilation-targets" "^7.15.0" - "@babel/helper-module-transforms" "^7.15.0" - "@babel/helpers" "^7.14.8" - "@babel/parser" "^7.15.0" - "@babel/template" "^7.14.5" - "@babel/traverse" "^7.15.0" - "@babel/types" "^7.15.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - source-map "^0.5.0" - -"@babel/generator@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15" - integrity sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ== - dependencies: - "@babel/types" "^7.15.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/helper-annotate-as-pure@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz#7bf478ec3b71726d56a8ca5775b046fc29879e61" - integrity sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz#b939b43f8c37765443a19ae74ad8b15978e0a191" - integrity sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.14.5" - "@babel/types" "^7.14.5" - -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.14.5", "@babel/helper-compilation-targets@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz#973df8cbd025515f3ff25db0c05efc704fa79818" - integrity sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A== - dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-validator-option" "^7.14.5" - browserslist "^4.16.6" - semver "^6.3.0" - -"@babel/helper-create-class-features-plugin@^7.14.5": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz#c9a137a4d137b2d0e2c649acf536d7ba1a76c0f7" - integrity sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q== - dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-member-expression-to-functions" "^7.15.0" - "@babel/helper-optimise-call-expression" "^7.14.5" - "@babel/helper-replace-supers" "^7.15.0" - "@babel/helper-split-export-declaration" "^7.14.5" - -"@babel/helper-create-regexp-features-plugin@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz#c7d5ac5e9cf621c26057722fb7a8a4c5889358c4" - integrity sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - regexpu-core "^4.7.1" - -"@babel/helper-define-polyfill-provider@^0.2.2": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz#0525edec5094653a282688d34d846e4c75e9c0b6" - integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew== - dependencies: - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/traverse" "^7.13.0" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" - -"@babel/helper-explode-assignable-expression@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz#8aa72e708205c7bb643e45c73b4386cdf2a1f645" - integrity sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-function-name@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz#89e2c474972f15d8e233b52ee8c480e2cfcd50c4" - integrity sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ== - dependencies: - "@babel/helper-get-function-arity" "^7.14.5" - "@babel/template" "^7.14.5" - "@babel/types" "^7.14.5" - -"@babel/helper-get-function-arity@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz#25fbfa579b0937eee1f3b805ece4ce398c431815" - integrity sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-hoist-variables@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz#e0dd27c33a78e577d7c8884916a3e7ef1f7c7f8d" - integrity sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-member-expression-to-functions@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz#0ddaf5299c8179f27f37327936553e9bba60990b" - integrity sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg== - dependencies: - "@babel/types" "^7.15.0" - -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz#6d1a44df6a38c957aa7c312da076429f11b422f3" - integrity sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz#679275581ea056373eddbe360e1419ef23783b08" - integrity sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg== - dependencies: - "@babel/helper-module-imports" "^7.14.5" - "@babel/helper-replace-supers" "^7.15.0" - "@babel/helper-simple-access" "^7.14.8" - "@babel/helper-split-export-declaration" "^7.14.5" - "@babel/helper-validator-identifier" "^7.14.9" - "@babel/template" "^7.14.5" - "@babel/traverse" "^7.15.0" - "@babel/types" "^7.15.0" - -"@babel/helper-optimise-call-expression@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz#f27395a8619e0665b3f0364cddb41c25d71b499c" - integrity sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" - integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== - -"@babel/helper-remap-async-to-generator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz#51439c913612958f54a987a4ffc9ee587a2045d6" - integrity sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - "@babel/helper-wrap-function" "^7.14.5" - "@babel/types" "^7.14.5" - -"@babel/helper-replace-supers@^7.14.5", "@babel/helper-replace-supers@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz#ace07708f5bf746bf2e6ba99572cce79b5d4e7f4" - integrity sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.15.0" - "@babel/helper-optimise-call-expression" "^7.14.5" - "@babel/traverse" "^7.15.0" - "@babel/types" "^7.15.0" - -"@babel/helper-simple-access@^7.14.8": - version "7.14.8" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz#82e1fec0644a7e775c74d305f212c39f8fe73924" - integrity sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg== - dependencies: - "@babel/types" "^7.14.8" - -"@babel/helper-skip-transparent-expression-wrappers@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz#96f486ac050ca9f44b009fbe5b7d394cab3a0ee4" - integrity sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-split-export-declaration@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz#22b23a54ef51c2b7605d851930c1976dd0bc693a" - integrity sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" - integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== - -"@babel/helper-validator-option@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" - integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== - -"@babel/helper-wrap-function@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz#5919d115bf0fe328b8a5d63bcb610f51601f2bff" - integrity sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ== - dependencies: - "@babel/helper-function-name" "^7.14.5" - "@babel/template" "^7.14.5" - "@babel/traverse" "^7.14.5" - "@babel/types" "^7.14.5" - -"@babel/helpers@^7.14.8": - version "7.15.3" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.3.tgz#c96838b752b95dcd525b4e741ed40bb1dc2a1357" - integrity sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g== - dependencies: - "@babel/template" "^7.14.5" - "@babel/traverse" "^7.15.0" - "@babel/types" "^7.15.0" - -"@babel/highlight@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" - integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== - dependencies: - "@babel/helper-validator-identifier" "^7.14.5" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.14.5", "@babel/parser@^7.15.0": - version "7.15.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.3.tgz#3416d9bea748052cfcb63dbcc27368105b1ed862" - integrity sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA== - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz#4b467302e1548ed3b1be43beae2cc9cf45e0bb7e" - integrity sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" - -"@babel/plugin-proposal-async-generator-functions@^7.14.9": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz#7028dc4fa21dc199bbacf98b39bab1267d0eaf9a" - integrity sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.14.5" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@^7.13.0", "@babel/plugin-proposal-class-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz#40d1ee140c5b1e31a350f4f5eed945096559b42e" - integrity sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-proposal-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz#158e9e10d449c3849ef3ecde94a03d9f1841b681" - integrity sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-proposal-dynamic-import@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz#0c6617df461c0c1f8fff3b47cd59772360101d2c" - integrity sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz#dbad244310ce6ccd083072167d8cea83a52faf76" - integrity sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-json-strings@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz#38de60db362e83a3d8c944ac858ddf9f0c2239eb" - integrity sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-json-strings" "^7.8.3" - -"@babel/plugin-proposal-logical-assignment-operators@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz#6e6229c2a99b02ab2915f82571e0cc646a40c738" - integrity sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz#ee38589ce00e2cc59b299ec3ea406fcd3a0fdaf6" - integrity sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - -"@babel/plugin-proposal-numeric-separator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz#83631bf33d9a51df184c2102a069ac0c58c05f18" - integrity sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.14.2", "@babel/plugin-proposal-object-rest-spread@^7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz#5920a2b3df7f7901df0205974c0641b13fd9d363" - integrity sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g== - dependencies: - "@babel/compat-data" "^7.14.7" - "@babel/helper-compilation-targets" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.14.5" - -"@babel/plugin-proposal-optional-catch-binding@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz#939dd6eddeff3a67fdf7b3f044b5347262598c3c" - integrity sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz#fa83651e60a360e3f13797eef00b8d519695b603" - integrity sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-proposal-private-methods@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz#37446495996b2945f30f5be5b60d5e2aa4f5792d" - integrity sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-proposal-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz#9f65a4d0493a940b4c01f8aa9d3f1894a587f636" - integrity sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q== - dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-proposal-unicode-property-regex@^7.14.5", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz#0f95ee0e757a5d647f378daa0eca7e93faa8bbe8" - integrity sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-arrow-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz#f7187d9588a768dd080bf4c9ffe117ea62f7862a" - integrity sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-async-to-generator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz#72c789084d8f2094acb945633943ef8443d39e67" - integrity sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA== - dependencies: - "@babel/helper-module-imports" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.14.5" - -"@babel/plugin-transform-block-scoped-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz#e48641d999d4bc157a67ef336aeb54bc44fd3ad4" - integrity sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-block-scoping@^7.14.5": - version "7.15.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz#94c81a6e2fc230bcce6ef537ac96a1e4d2b3afaf" - integrity sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-classes@^7.14.9": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz#2a391ffb1e5292710b00f2e2c210e1435e7d449f" - integrity sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-optimise-call-expression" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.14.5" - "@babel/helper-split-export-declaration" "^7.14.5" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz#1b9d78987420d11223d41195461cc43b974b204f" - integrity sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-destructuring@^7.13.17", "@babel/plugin-transform-destructuring@^7.14.7": - version "7.14.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz#0ad58ed37e23e22084d109f185260835e5557576" - integrity sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-dotall-regex@^7.14.5", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz#2f6bf76e46bdf8043b4e7e16cf24532629ba0c7a" - integrity sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-duplicate-keys@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz#365a4844881bdf1501e3a9f0270e7f0f91177954" - integrity sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-exponentiation-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz#5154b8dd6a3dfe6d90923d61724bd3deeb90b493" - integrity sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-for-of@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz#dae384613de8f77c196a8869cbf602a44f7fc0eb" - integrity sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-function-name@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz#e81c65ecb900746d7f31802f6bed1f52d915d6f2" - integrity sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ== - dependencies: - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz#41d06c7ff5d4d09e3cf4587bd3ecf3930c730f78" - integrity sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-member-expression-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz#b39cd5212a2bf235a617d320ec2b48bcc091b8a7" - integrity sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-modules-amd@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz#4fd9ce7e3411cb8b83848480b7041d83004858f7" - integrity sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g== - dependencies: - "@babel/helper-module-transforms" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-commonjs@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz#3305896e5835f953b5cdb363acd9e8c2219a5281" - integrity sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig== - dependencies: - "@babel/helper-module-transforms" "^7.15.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-simple-access" "^7.14.8" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-systemjs@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz#c75342ef8b30dcde4295d3401aae24e65638ed29" - integrity sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA== - dependencies: - "@babel/helper-hoist-variables" "^7.14.5" - "@babel/helper-module-transforms" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-identifier" "^7.14.5" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-umd@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz#fb662dfee697cce274a7cda525190a79096aa6e0" - integrity sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA== - dependencies: - "@babel/helper-module-transforms" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.14.9": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz#c68f5c5d12d2ebaba3762e57c2c4f6347a46e7b2" - integrity sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" - -"@babel/plugin-transform-new-target@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz#31bdae8b925dc84076ebfcd2a9940143aed7dbf8" - integrity sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-object-super@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz#d0b5faeac9e98597a161a9cf78c527ed934cdc45" - integrity sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.14.5" - -"@babel/plugin-transform-parameters@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz#49662e86a1f3ddccac6363a7dfb1ff0a158afeb3" - integrity sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-property-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz#0ddbaa1f83db3606f1cdf4846fa1dfb473458b34" - integrity sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-regenerator@^7.13.15", "@babel/plugin-transform-regenerator@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz#9676fd5707ed28f522727c5b3c0aa8544440b04f" - integrity sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-reserved-words@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz#c44589b661cfdbef8d4300dcc7469dffa92f8304" - integrity sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-runtime@^7.14.3": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.15.0.tgz#d3aa650d11678ca76ce294071fda53d7804183b3" - integrity sha512-sfHYkLGjhzWTq6xsuQ01oEsUYjkHRux9fW1iUA68dC7Qd8BS1Unq4aZ8itmQp95zUzIcyR2EbNMTzAicFj+guw== - dependencies: - "@babel/helper-module-imports" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.2" - babel-plugin-polyfill-regenerator "^0.2.2" - semver "^6.3.0" - -"@babel/plugin-transform-shorthand-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz#97f13855f1409338d8cadcbaca670ad79e091a58" - integrity sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-spread@^7.14.6": - version "7.14.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz#6bd40e57fe7de94aa904851963b5616652f73144" - integrity sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" - -"@babel/plugin-transform-sticky-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz#5b617542675e8b7761294381f3c28c633f40aeb9" - integrity sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-template-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz#a5f2bc233937d8453885dc736bdd8d9ffabf3d93" - integrity sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-typeof-symbol@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz#39af2739e989a2bd291bf6b53f16981423d457d4" - integrity sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-unicode-escapes@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz#9d4bd2a681e3c5d7acf4f57fa9e51175d91d0c6b" - integrity sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-unicode-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz#4cd09b6c8425dd81255c7ceb3fb1836e7414382e" - integrity sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/preset-env@^7.14.2": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.15.0.tgz#e2165bf16594c9c05e52517a194bf6187d6fe464" - integrity sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q== - dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-compilation-targets" "^7.15.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-async-generator-functions" "^7.14.9" - "@babel/plugin-proposal-class-properties" "^7.14.5" - "@babel/plugin-proposal-class-static-block" "^7.14.5" - "@babel/plugin-proposal-dynamic-import" "^7.14.5" - "@babel/plugin-proposal-export-namespace-from" "^7.14.5" - "@babel/plugin-proposal-json-strings" "^7.14.5" - "@babel/plugin-proposal-logical-assignment-operators" "^7.14.5" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" - "@babel/plugin-proposal-numeric-separator" "^7.14.5" - "@babel/plugin-proposal-object-rest-spread" "^7.14.7" - "@babel/plugin-proposal-optional-catch-binding" "^7.14.5" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-private-methods" "^7.14.5" - "@babel/plugin-proposal-private-property-in-object" "^7.14.5" - "@babel/plugin-proposal-unicode-property-regex" "^7.14.5" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.14.5" - "@babel/plugin-transform-async-to-generator" "^7.14.5" - "@babel/plugin-transform-block-scoped-functions" "^7.14.5" - "@babel/plugin-transform-block-scoping" "^7.14.5" - "@babel/plugin-transform-classes" "^7.14.9" - "@babel/plugin-transform-computed-properties" "^7.14.5" - "@babel/plugin-transform-destructuring" "^7.14.7" - "@babel/plugin-transform-dotall-regex" "^7.14.5" - "@babel/plugin-transform-duplicate-keys" "^7.14.5" - "@babel/plugin-transform-exponentiation-operator" "^7.14.5" - "@babel/plugin-transform-for-of" "^7.14.5" - "@babel/plugin-transform-function-name" "^7.14.5" - "@babel/plugin-transform-literals" "^7.14.5" - "@babel/plugin-transform-member-expression-literals" "^7.14.5" - "@babel/plugin-transform-modules-amd" "^7.14.5" - "@babel/plugin-transform-modules-commonjs" "^7.15.0" - "@babel/plugin-transform-modules-systemjs" "^7.14.5" - "@babel/plugin-transform-modules-umd" "^7.14.5" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.9" - "@babel/plugin-transform-new-target" "^7.14.5" - "@babel/plugin-transform-object-super" "^7.14.5" - "@babel/plugin-transform-parameters" "^7.14.5" - "@babel/plugin-transform-property-literals" "^7.14.5" - "@babel/plugin-transform-regenerator" "^7.14.5" - "@babel/plugin-transform-reserved-words" "^7.14.5" - "@babel/plugin-transform-shorthand-properties" "^7.14.5" - "@babel/plugin-transform-spread" "^7.14.6" - "@babel/plugin-transform-sticky-regex" "^7.14.5" - "@babel/plugin-transform-template-literals" "^7.14.5" - "@babel/plugin-transform-typeof-symbol" "^7.14.5" - "@babel/plugin-transform-unicode-escapes" "^7.14.5" - "@babel/plugin-transform-unicode-regex" "^7.14.5" - "@babel/preset-modules" "^0.1.4" - "@babel/types" "^7.15.0" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.2" - babel-plugin-polyfill-regenerator "^0.2.2" - core-js-compat "^3.16.0" - semver "^6.3.0" - -"@babel/preset-modules@^0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" - integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/runtime@^7.14.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4": - version "7.15.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b" - integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" - integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/parser" "^7.14.5" - "@babel/types" "^7.14.5" - -"@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.15.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.0.tgz#4cca838fd1b2a03283c1f38e141f639d60b3fc98" - integrity sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.15.0" - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-hoist-variables" "^7.14.5" - "@babel/helper-split-export-declaration" "^7.14.5" - "@babel/parser" "^7.15.0" - "@babel/types" "^7.15.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.14.5", "@babel/types@^7.14.8", "@babel/types@^7.15.0", "@babel/types@^7.4.4": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.0.tgz#61af11f2286c4e9c69ca8deb5f4375a73c72dcbd" - integrity sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ== - dependencies: - "@babel/helper-validator-identifier" "^7.14.9" - to-fast-properties "^2.0.0" - -"@csstools/convert-colors@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" - integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== - -"@hotwired/turbo-rails@^7.0.0-rc.1": - version "7.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@hotwired/turbo-rails/-/turbo-rails-7.0.0-rc.1.tgz#68cc07b2a1e7d9b29240c525c657722b3f0c3842" - integrity sha512-LLOgtHWb/cnz0bXlfJ9khWHapQuCOuUI48yiSVgL3veklvbX1vyQlk/ALn35Z6nHTi7Bf+MHMS9H5W2c/vwKuw== - dependencies: - "@hotwired/turbo" "^7.0.0-rc.1" - "@rails/actioncable" "^6.0.0" - -"@hotwired/turbo@^7.0.0-rc.1": - version "7.0.0-rc.1" - resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-7.0.0-rc.1.tgz#a5c1be86def1cc39b3011c935c5734b8632af5c3" - integrity sha512-niNA68ku4TZYbV3biwTPf1L5CidP50S2xfeb5rGQfodvPB9UAtkqKFFRIA0LL8y0DG4MGIZ/QFlbvlmFea5p4w== - -"@npmcli/move-file@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" - integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== - dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" - -"@rails/actioncable@^6.0.0": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.4.tgz#c3c5a9f8302c429af9722b6c50ab48049016d2a3" - integrity sha512-0LmSKJTuo2dL6BQ+9xxLnS9lbkyfz2mBGeBnQ2J7o9Bn0l0q+ZC6VuoZMZZXPvABI4QT7Nfknv5WhfKYL+boew== - -"@rails/actiontext@^6.0.3-6": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@rails/actiontext/-/actiontext-6.1.4.tgz#ed8c7d2b68d66205301f4538ce65d04c48031f6b" - integrity sha512-KG+VCofmfZAhW1x1xFxMC2sZtvwbx+XX0Y+dzeBFjKU1jZMM0RNytJf5EiuHtD9fL71zz6/nMT7FjwOFenSA7Q== - dependencies: - "@rails/activestorage" "^6.0.0" - -"@rails/activestorage@^6.0.0", "@rails/activestorage@^6.0.3-4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@rails/activestorage/-/activestorage-6.1.4.tgz#7772f539cc846df5f4364fc57ccb48860f9e966e" - integrity sha512-1Tm8uaVBhLTDEG4YaFPvqguhjbUGSPVItm0CfkRpIFZIkybWzFAxatIrk4YVOOxB8ZdXS7GdeYa1qVwjdiDkgQ== - dependencies: - spark-md5 "^3.0.0" - -"@rails/ujs@~6.0": - version "6.0.4" - resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.0.4.tgz#b155b0e23b766fe8038cb9bc796efb55ea840c15" - integrity sha512-pi6BTIAuMAgfh0tz9jHyKwuzT8HKWlZdfI6/pxcR+NWRuTyN9psYmxskP2QnxFehSkSuvQmQuKv3Hyrs13l3xQ== - -"@rails/webpacker@^5.2.1": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@rails/webpacker/-/webpacker-5.4.0.tgz#2c64a9ea7e85d2a33e50e86319fe6751df0c47e8" - integrity sha512-J973mzTUJbkbBu+sMwKgWRahoSfwdp5uHT80iDWr6hi8YAC7kj47HapQnn2SGPmv/onTT8WC3jFM62Hkh213yQ== - dependencies: - "@babel/core" "^7.14.3" - "@babel/plugin-proposal-class-properties" "^7.13.0" - "@babel/plugin-proposal-object-rest-spread" "^7.14.2" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.13.17" - "@babel/plugin-transform-regenerator" "^7.13.15" - "@babel/plugin-transform-runtime" "^7.14.3" - "@babel/preset-env" "^7.14.2" - "@babel/runtime" "^7.14.0" - babel-loader "^8.2.2" - babel-plugin-dynamic-import-node "^2.3.3" - babel-plugin-macros "^2.8.0" - case-sensitive-paths-webpack-plugin "^2.4.0" - compression-webpack-plugin "^4.0.1" - core-js "^3.12.1" - css-loader "^3.6.0" - file-loader "^6.2.0" - flatted "^3.1.1" - glob "^7.1.7" - js-yaml "^3.14.1" - mini-css-extract-plugin "^0.9.0" - optimize-css-assets-webpack-plugin "^5.0.6" - path-complete-extname "^1.0.0" - pnp-webpack-plugin "^1.6.4" - postcss-flexbugs-fixes "^4.2.1" - postcss-import "^12.0.1" - postcss-loader "^3.0.0" - postcss-preset-env "^6.7.0" - postcss-safe-parser "^4.0.2" - regenerator-runtime "^0.13.7" - sass "^1.32.13" - sass-loader "10.1.1" - style-loader "^1.3.0" - terser-webpack-plugin "^4.2.3" - webpack "^4.46.0" - webpack-assets-manifest "^3.1.1" - webpack-cli "^3.3.12" - webpack-sources "^1.4.3" - -"@sentry/browser@^5.29.2": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.30.0.tgz#c28f49d551db3172080caef9f18791a7fd39e3b3" - integrity sha512-rOb58ZNVJWh1VuMuBG1mL9r54nZqKeaIlwSlvzJfc89vyfd7n6tQ1UXMN383QBz/MS5H5z44Hy5eE+7pCrYAfw== - dependencies: - "@sentry/core" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/core@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" - integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/minimal" "5.30.0" - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/hub@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" - integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== - dependencies: - "@sentry/types" "5.30.0" - "@sentry/utils" "5.30.0" - tslib "^1.9.3" - -"@sentry/minimal@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" - integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== - dependencies: - "@sentry/hub" "5.30.0" - "@sentry/types" "5.30.0" - tslib "^1.9.3" - -"@sentry/types@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" - integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== - -"@sentry/utils@5.30.0": - version "5.30.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" - integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== - dependencies: - "@sentry/types" "5.30.0" - tslib "^1.9.3" - -"@stimulus/core@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@stimulus/core/-/core-2.0.0.tgz#140c85318d6a8a8210c0faf182223b8459348877" - integrity sha512-ff70GafKtzc8zQ1/cG+UvL06GcifPWovf2wBEdjLMh9xO2GOYURO3y2RYgzIGYUIBefQwyfX2CLfJdZFJrEPTw== - dependencies: - "@stimulus/mutation-observers" "^2.0.0" - -"@stimulus/multimap@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@stimulus/multimap/-/multimap-2.0.0.tgz#420cfa096ed6538df4a91dbd2b2842c1779952b2" - integrity sha512-pMBCewkZCFVB3e5mEMoyO9+9aKzHDITmf3OnPun51YWxlcPdHcwbjqm1ylK63fsoduIE+RowBpFwFqd3poEz4w== - -"@stimulus/mutation-observers@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@stimulus/mutation-observers/-/mutation-observers-2.0.0.tgz#3dbe37453bda47a6c795a90204ee8d77a799fb87" - integrity sha512-kx4VAJdPhIGBQKGIoUDC2tupEKorG3A+ckc2b1UiwInKTMAC1axOHU8ebcwhaJIxRqIrs8//4SJo9YAAOx6FEg== - dependencies: - "@stimulus/multimap" "^2.0.0" - -"@stimulus/webpack-helpers@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@stimulus/webpack-helpers/-/webpack-helpers-2.0.0.tgz#54296d2a2dffd4f962d2e802d99a3fdd84b8845f" - integrity sha512-D6tJWsAC024MwGEIKlUVYU8Ln87mlrmiwHvYAjipg+s8H4eLxUMQ3PZkWyPevfipH+oR3leuHsjYsK1gN5ViQA== - -"@types/glob@^7.1.1": - version "7.1.4" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.4.tgz#ea59e21d2ee5c517914cb4bc8e4153b99e566672" - integrity sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - -"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== - -"@types/minimatch@*": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" - integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== - -"@types/node@*": - version "16.6.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.1.tgz#aee62c7b966f55fc66c7b6dfa1d58db2a616da61" - integrity sha512-Sr7BhXEAer9xyGuCN3Ek9eg9xPviCF2gfu9kTfuU2HkTVAMYSDeX40fvpmo72n5nansg3nsBjuQBrsS28r+NUw== - -"@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== - -"@types/q@^1.5.1": - version "1.5.5" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df" - integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ== - -"@webassemblyjs/ast@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" - integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== - dependencies: - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" - -"@webassemblyjs/floating-point-hex-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" - integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== - -"@webassemblyjs/helper-api-error@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" - integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== - -"@webassemblyjs/helper-buffer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" - integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== - -"@webassemblyjs/helper-code-frame@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" - integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== - dependencies: - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/helper-fsm@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" - integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== - -"@webassemblyjs/helper-module-context@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" - integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== - dependencies: - "@webassemblyjs/ast" "1.9.0" - -"@webassemblyjs/helper-wasm-bytecode@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" - integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== - -"@webassemblyjs/helper-wasm-section@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" - integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - -"@webassemblyjs/ieee754@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" - integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" - integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" - integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== - -"@webassemblyjs/wasm-edit@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" - integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/helper-wasm-section" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-opt" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/wasm-gen@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" - integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" - -"@webassemblyjs/wasm-opt@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" - integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - -"@webassemblyjs/wasm-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" - integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" - -"@webassemblyjs/wast-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" - integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/floating-point-hex-parser" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-code-frame" "1.9.0" - "@webassemblyjs/helper-fsm" "1.9.0" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/wast-printer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" - integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" - "@xtuc/long" "4.2.2" - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn@^6.4.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== - -ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -alphanum-sort@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= - -ansi-colors@^3.0.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" - integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== - -ansi-html@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" - integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -aproba@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-flatten@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - -async@^2.6.2: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -autoprefixer@^10.3.1: - version "10.3.1" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.3.1.tgz#954214821d3aa06692406c6a0a9e9d401eafbed2" - integrity sha512-L8AmtKzdiRyYg7BUXJTzigmhbQRCXFKz6SA1Lqo0+AR2FBbQ4aTAPFSDlOutnFkjhiz8my4agGXog1xlMjPJ6A== - dependencies: - browserslist "^4.16.6" - caniuse-lite "^1.0.30001243" - colorette "^1.2.2" - fraction.js "^4.1.1" - normalize-range "^0.1.2" - postcss-value-parser "^4.1.0" - -autoprefixer@^9.6.1: - version "9.8.6" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" - integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== - dependencies: - browserslist "^4.12.0" - caniuse-lite "^1.0.30001109" - colorette "^1.2.1" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^7.0.32" - postcss-value-parser "^4.1.0" - -babel-loader@^8.2.2: - version "8.2.2" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" - integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== - dependencies: - find-cache-dir "^3.3.1" - loader-utils "^1.4.0" - make-dir "^3.1.0" - schema-utils "^2.6.5" - -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== - dependencies: - object.assign "^4.1.0" - -babel-plugin-macros@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" - integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== - dependencies: - "@babel/runtime" "^7.7.2" - cosmiconfig "^6.0.0" - resolve "^1.12.0" - -babel-plugin-polyfill-corejs2@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz#e9124785e6fd94f94b618a7954e5693053bf5327" - integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ== - dependencies: - "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.2.2" - semver "^6.1.1" - -babel-plugin-polyfill-corejs3@^0.2.2: - version "0.2.4" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.4.tgz#68cb81316b0e8d9d721a92e0009ec6ecd4cd2ca9" - integrity sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" - core-js-compat "^3.14.0" - -babel-plugin-polyfill-regenerator@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz#b310c8d642acada348c1fa3b3e6ce0e851bee077" - integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.0.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bluebird@^3.5.5: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.0.0, bn.js@^5.1.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" - integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== - -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= - dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" - dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -brorand@^1.0.1, brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.6, browserslist@^4.16.7, browserslist@^4.6.4: - version "4.16.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.7.tgz#108b0d1ef33c4af1b587c54f390e7041178e4335" - integrity sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA== - dependencies: - caniuse-lite "^1.0.30001248" - colorette "^1.2.2" - electron-to-chromium "^1.3.793" - escalade "^3.1.1" - node-releases "^1.1.73" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - -buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -cacache@^12.0.2: - version "12.0.4" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" - integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== - dependencies: - bluebird "^3.5.5" - chownr "^1.1.1" - figgy-pudding "^3.5.1" - glob "^7.1.4" - graceful-fs "^4.1.15" - infer-owner "^1.0.3" - lru-cache "^5.1.1" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.3" - ssri "^6.0.1" - unique-filename "^1.1.1" - y18n "^4.0.0" - -cacache@^15.0.5: - version "15.2.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.2.0.tgz#73af75f77c58e72d8c630a7a2858cb18ef523389" - integrity sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw== - dependencies: - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.0.0, camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001243, caniuse-lite@^1.0.30001248: - version "1.0.30001251" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz#6853a606ec50893115db660f82c094d18f096d85" - integrity sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A== - -case-sensitive-paths-webpack-plugin@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4" - integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw== - -chalk@^2.0, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -coa@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== - dependencies: - "@types/q" "^1.5.1" - chalk "^2.4.1" - q "^1.1.2" - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0, color-convert@^1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-string@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.6.0.tgz#c3915f61fe267672cb7e1e064c9d692219f6c312" - integrity sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color@^3.0.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" - integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== - dependencies: - color-convert "^1.9.3" - color-string "^1.6.0" - -colorette@^1.2.1, colorette@^1.2.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.3.0.tgz#ff45d2f0edb244069d3b772adeb04fed38d0a0af" - integrity sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -compressible@~2.0.16: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression-webpack-plugin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-4.0.1.tgz#33eda97f1170dd38c5556771de10f34245aa0274" - integrity sha512-0mg6PgwTsUe5LEcUrOu3ob32vraDx2VdbMGAT1PARcOV+UJWDYZFdkSo6RbHoGQ061mmmkC7XpRKOlvwm/gzJQ== - dependencies: - cacache "^15.0.5" - find-cache-dir "^3.3.1" - schema-utils "^2.7.0" - serialize-javascript "^4.0.0" - webpack-sources "^1.4.3" - -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@^1.5.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== - -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -copy-concurrently@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== - dependencies: - aproba "^1.1.1" - fs-write-stream-atomic "^1.0.8" - iferr "^0.1.5" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.0" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -core-js-compat@^3.14.0, core-js-compat@^3.16.0: - version "3.16.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.16.1.tgz#c44b7caa2dcb94b673a98f27eee1c8312f55bc2d" - integrity sha512-NHXQXvRbd4nxp9TEmooTJLUf94ySUG6+DSsscBpTftN1lQLQ4LjnWvc7AoIo4UjDsFF3hB8Uh5LLCRRdaiT5MQ== - dependencies: - browserslist "^4.16.7" - semver "7.0.0" - -core-js@^3.12.1: - version "3.16.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.16.1.tgz#f4485ce5c9f3c6a7cb18fa80488e08d362097249" - integrity sha512-AAkP8i35EbefU+JddyWi12AWE9f2N/qr/pwnDtWz4nyUIBGMJPX99ANFFRSw6FefM374lDujdtLDyhN2A/btHw== - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cosmiconfig@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -cosmiconfig@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" - integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.7.2" - -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cross-spawn@^6.0.0, cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -css-blank-pseudo@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" - integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== - dependencies: - postcss "^7.0.5" - -css-color-names@0.0.4, css-color-names@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= - -css-declaration-sorter@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== - dependencies: - postcss "^7.0.1" - timsort "^0.3.0" - -css-has-pseudo@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" - integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== - dependencies: - postcss "^7.0.6" - postcss-selector-parser "^5.0.0-rc.4" - -css-loader@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" - integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== - dependencies: - camelcase "^5.3.1" - cssesc "^3.0.0" - icss-utils "^4.1.1" - loader-utils "^1.2.3" - normalize-path "^3.0.0" - postcss "^7.0.32" - postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^3.0.2" - postcss-modules-scope "^2.2.0" - postcss-modules-values "^3.0.0" - postcss-value-parser "^4.1.0" - schema-utils "^2.7.0" - semver "^6.3.0" - -css-prefers-color-scheme@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" - integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== - dependencies: - postcss "^7.0.5" - -css-select-base-adapter@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== - -css-select@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" - integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== - dependencies: - boolbase "^1.0.0" - css-what "^3.2.1" - domutils "^1.7.0" - nth-check "^1.0.2" - -css-tree@1.0.0-alpha.37: - version "1.0.0-alpha.37" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" - integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== - dependencies: - mdn-data "2.0.4" - source-map "^0.6.1" - -css-tree@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" - integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== - dependencies: - mdn-data "2.0.14" - source-map "^0.6.1" - -css-what@^3.2.1: - version "3.4.2" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" - integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== - -cssdb@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" - integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== - -cssesc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-default@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz#920622b1fc1e95a34e8838203f1397a504f2d3ff" - integrity sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ== - dependencies: - css-declaration-sorter "^4.0.1" - cssnano-util-raw-cache "^4.0.1" - postcss "^7.0.0" - postcss-calc "^7.0.1" - postcss-colormin "^4.0.3" - postcss-convert-values "^4.0.1" - postcss-discard-comments "^4.0.2" - postcss-discard-duplicates "^4.0.2" - postcss-discard-empty "^4.0.1" - postcss-discard-overridden "^4.0.1" - postcss-merge-longhand "^4.0.11" - postcss-merge-rules "^4.0.3" - postcss-minify-font-values "^4.0.2" - postcss-minify-gradients "^4.0.2" - postcss-minify-params "^4.0.2" - postcss-minify-selectors "^4.0.2" - postcss-normalize-charset "^4.0.1" - postcss-normalize-display-values "^4.0.2" - postcss-normalize-positions "^4.0.2" - postcss-normalize-repeat-style "^4.0.2" - postcss-normalize-string "^4.0.2" - postcss-normalize-timing-functions "^4.0.2" - postcss-normalize-unicode "^4.0.1" - postcss-normalize-url "^4.0.1" - postcss-normalize-whitespace "^4.0.2" - postcss-ordered-values "^4.1.2" - postcss-reduce-initial "^4.0.3" - postcss-reduce-transforms "^4.0.2" - postcss-svgo "^4.0.3" - postcss-unique-selectors "^4.0.1" - -cssnano-util-get-arguments@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= - -cssnano-util-get-match@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= - -cssnano-util-raw-cache@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== - dependencies: - postcss "^7.0.0" - -cssnano-util-same-parent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== - -cssnano@^4.1.10: - version "4.1.11" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.11.tgz#c7b5f5b81da269cb1fd982cb960c1200910c9a99" - integrity sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g== - dependencies: - cosmiconfig "^5.0.0" - cssnano-preset-default "^4.0.8" - is-resolvable "^1.0.0" - postcss "^7.0.0" - -csso@^4.0.2: - version "4.2.0" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" - integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== - dependencies: - css-tree "^1.1.2" - -cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" - integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.1.1, debug@^3.2.6: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.0, debug@^4.1.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -default-gateway@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" - integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== - dependencies: - execa "^1.0.0" - ip-regex "^2.1.0" - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -del@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" - integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== - dependencies: - "@types/glob" "^7.1.1" - globby "^6.1.0" - is-path-cwd "^2.0.0" - is-path-in-cwd "^2.0.0" - p-map "^2.0.0" - pify "^4.0.1" - rimraf "^2.6.3" - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detect-file@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" - integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= - -detect-node@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" - -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= - dependencies: - buffer-indexof "^1.0.0" - -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - -domelementtype@1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domutils@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -dot-prop@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" - integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== - dependencies: - is-obj "^2.0.0" - -duplexify@^3.4.2, duplexify@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.3.793: - version "1.3.805" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.805.tgz#a0873393a3b027ec60bdaf22a19c4946688cf941" - integrity sha512-uUJF59M6pNSRHQaXwdkaNB4BhSQ9lldRdG1qCjlrAFkynPGDc5wPoUcYEQQeQGmKyAWJPvGkYAWmtVrxWmDAkg== - -elliptic@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" - integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.5.0" - tapable "^1.0.0" - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -errno@^0.1.3, errno@~0.1.7: - version "0.1.8" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" - integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== - dependencies: - prr "~1.0.1" - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.17.2, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2: - version "1.18.5" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.5.tgz#9b10de7d4c206a3581fd5b2124233e04db49ae19" - integrity sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.3" - is-negative-zero "^2.0.1" - is-regex "^1.1.3" - is-string "^1.0.6" - object-inspect "^1.11.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esrecurse@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -eventsource@^1.0.7: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.0.tgz#00e8ca7c92109e94b0ddf32dac677d841028cfaf" - integrity sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg== - dependencies: - original "^1.0.0" - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= - dependencies: - homedir-polyfill "^1.0.1" - -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -fast-deep-equal@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -faye-websocket@^0.11.3: - version "0.11.4" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" - integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== - dependencies: - websocket-driver ">=0.5.1" - -figgy-pudding@^3.5.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" - integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== - -file-loader@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" - integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-cache-dir@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" - integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -findup-sync@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" - integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== - dependencies: - detect-file "^1.0.0" - is-glob "^4.0.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - -flatted@^3.1.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" - integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== - -flatten@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" - integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== - -flush-write-stream@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" - integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== - dependencies: - inherits "^2.0.3" - readable-stream "^2.3.6" - -follow-redirects@^1.0.0: - version "1.14.8" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" - integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fraction.js@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.1.tgz#ac4e520473dae67012d618aab91eda09bcb400ff" - integrity sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg== - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -from2@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.0" - -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - -fs-write-stream-atomic@^1.0.8: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= - dependencies: - graceful-fs "^4.1.2" - iferr "^0.1.5" - imurmurhash "^0.1.4" - readable-stream "1 || 2" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - -fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@^7.0.3, glob@^7.1.3, glob@^7.1.4, glob@^7.1.7: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== - dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" - -global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= - dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" - -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== - -halfmoon@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/halfmoon/-/halfmoon-1.1.1.tgz#af45c2d78bb869a408a5b72bbac2dccbe89d2aed" - integrity sha512-w/ydT3CixxxxdJP4a3sqSzUnCJFmhvcqE2vQOIsWCfevpqanKlbGQNUwKJH0nKvo13M89eetM3R0gsTOfNLGHA== - -handle-thing@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" - integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== - -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.0, has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -hex-color-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" - integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -hsl-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" - integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= - -hsla-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" - integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= - -html-entities@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" - integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-parser-js@>=0.5.1: - version "0.5.3" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" - integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== - -http-proxy-middleware@0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" - integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== - dependencies: - http-proxy "^1.17.0" - is-glob "^4.0.0" - lodash "^4.17.11" - micromatch "^3.1.10" - -http-proxy@^1.17.0: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -icss-utils@^4.0.0, icss-utils@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" - integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== - dependencies: - postcss "^7.0.14" - -ieee754@^1.1.4: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -iferr@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= - -import-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" - integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= - dependencies: - import-from "^2.1.0" - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - -import-fresh@^3.1.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-from@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" - integrity sha1-M1238qev/VOqpHHUuAId7ja387E= - dependencies: - resolve-from "^3.0.0" - -import-local@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - -infer-owner@^1.0.3, infer-owner@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.4, ini@^1.3.5: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -internal-ip@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" - integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== - dependencies: - default-gateway "^4.2.0" - ipaddr.js "^1.9.0" - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -interpret@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= - -ip@^1.1.0, ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - -ipaddr.js@1.9.1, ipaddr.js@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= - -is-absolute-url@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" - integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-callable@^1.1.4, is-callable@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-color-stop@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" - integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= - dependencies: - css-color-names "^0.0.4" - hex-color-regex "^1.1.0" - hsl-regex "^1.0.0" - hsla-regex "^1.0.0" - rgb-regex "^1.0.1" - rgba-regex "^1.0.0" - -is-core-module@^2.2.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491" - integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg== - dependencies: - has "^1.0.3" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== - -is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-cwd@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-in-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" - integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== - dependencies: - is-path-inside "^2.1.0" - -is-path-inside@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" - integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== - dependencies: - path-is-inside "^1.0.2" - -is-plain-obj@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.0.4, is-regex@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-string@^1.0.5, is-string@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-windows@^1.0.1, is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -jest-worker@^26.5.0: - version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" - integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^7.0.0" - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1, js-yaml@^3.14.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json3@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" - integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -killable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" - integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -klona@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" - integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== - -last-call-webpack-plugin@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" - integrity sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w== - dependencies: - lodash "^4.17.5" - webpack-sources "^1.1.0" - -lines-and-columns@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" - integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= - -loader-runner@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" - integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== - -loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - -loader-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" - integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.get@^4.0: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - -lodash.has@^4.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/lodash.has/-/lodash.has-4.5.2.tgz#d19f4dc1095058cccbe2b0cdf4ee0fe4aa37c862" - integrity sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI= - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.5: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loglevel@^1.6.8: - version "1.7.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" - integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -make-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-dir@^3.0.2, make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -mdn-data@2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" - integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== - -mdn-data@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" - integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -memory-fs@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -memory-fs@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" - integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.49.0, "mime-db@>= 1.43.0 < 2": - version "1.49.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" - integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== - -mime-types@~2.1.17, mime-types@~2.1.24: - version "2.1.32" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" - integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== - dependencies: - mime-db "1.49.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@^2.4.4: - version "2.5.2" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" - integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== - -mini-css-extract-plugin@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" - integrity sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A== - dependencies: - loader-utils "^1.1.0" - normalize-url "1.9.1" - schema-utils "^1.0.0" - webpack-sources "^1.1.0" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - -minipass-collect@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" - integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== - dependencies: - minipass "^3.0.0" - -minipass-flush@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" - integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== - dependencies: - minipass "^3.0.0" - -minipass-pipeline@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" - integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== - dependencies: - minipass "^3.0.0" - -minipass@^3.0.0, minipass@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" - integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== - dependencies: - yallist "^4.0.0" - -minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - -mississippi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^3.0.0" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@^0.5, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mkdirp@^1.0.3, mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -move-concurrently@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= - dependencies: - aproba "^1.1.1" - copy-concurrently "^1.0.0" - fs-write-stream-atomic "^1.0.8" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.3" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== - dependencies: - dns-packet "^1.3.1" - thunky "^1.0.2" - -nan@^2.12.1: - version "2.15.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" - integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== - -nanoid@^3.1.23: - version "3.3.2" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557" - integrity sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -node-forge@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" - integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== - -node-libs-browser@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - -node-releases@^1.1.73: - version "1.1.74" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.74.tgz#e5866488080ebaa70a93b91144ccde06f3c3463e" - integrity sha512-caJBVempXZPepZoZAPCWRTNxYQ+xtG/KAi4ozTA5A+nJ7IU+kLQCbqaUjb5Rwy14M9upBWiQ4NutcmW04LJSRw== - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - -normalize-url@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" - integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= - dependencies: - object-assign "^4.0.1" - prepend-http "^1.0.0" - query-string "^4.1.0" - sort-keys "^1.0.0" - -normalize-url@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -nth-check@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= - -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@^4.1.0, object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -object.getownpropertydescriptors@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7" - integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -object.values@^1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30" - integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.2" - -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -opn@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" - integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== - dependencies: - is-wsl "^1.1.0" - -optimize-css-assets-webpack-plugin@^5.0.6: - version "5.0.8" - resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.8.tgz#cbccdcf5a6ef61d4f8cc78cf083a67446e5f402a" - integrity sha512-mgFS1JdOtEGzD8l+EuISqL57cKO+We9GcoiQEmdCWRqqck+FGNmYJtx9qfAPzEz+lRrlThWMuGDaRkI/yWNx/Q== - dependencies: - cssnano "^4.1.10" - last-call-webpack-plugin "^3.0.0" - -original@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" - integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== - dependencies: - url-parse "^1.4.3" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-map@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - -p-retry@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" - integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== - dependencies: - retry "^0.12.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -pako@~1.0.5: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -parallel-transform@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" - integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== - dependencies: - cyclist "^1.0.1" - inherits "^2.0.3" - readable-stream "^2.1.5" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-json@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - -path-complete-extname@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/path-complete-extname/-/path-complete-extname-1.0.0.tgz#f889985dc91000c815515c0bfed06c5acda0752b" - integrity sha512-CVjiWcMRdGU8ubs08YQVzhutOR5DEfO97ipRIlOGMK5Bek5nQySknBpuxVAVJ36hseTNs+vdIcv57ZrWxH7zvg== - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-parse@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pbkdf2@^3.0.3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -picomatch@^2.0.4, picomatch@^2.2.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== - -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pkg-dir@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pnp-webpack-plugin@^1.6.4: - version "1.7.0" - resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz#65741384f6d8056f36e2255a8d67ffc20866f5c9" - integrity sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg== - dependencies: - ts-pnp "^1.1.6" - -portfinder@^1.0.26: - version "1.0.28" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postcss-attribute-case-insensitive@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" - integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^6.0.2" - -postcss-calc@^7.0.1: - version "7.0.5" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.5.tgz#f8a6e99f12e619c2ebc23cf6c486fdc15860933e" - integrity sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg== - dependencies: - postcss "^7.0.27" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.2" - -postcss-color-functional-notation@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" - integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-color-gray@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" - integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.5" - postcss-values-parser "^2.0.0" - -postcss-color-hex-alpha@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" - integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== - dependencies: - postcss "^7.0.14" - postcss-values-parser "^2.0.1" - -postcss-color-mod-function@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" - integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-color-rebeccapurple@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" - integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-colormin@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" - integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== - dependencies: - browserslist "^4.0.0" - color "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-convert-values@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-custom-media@^7.0.8: - version "7.0.8" - resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" - integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== - dependencies: - postcss "^7.0.14" - -postcss-custom-properties@^8.0.11: - version "8.0.11" - resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" - integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== - dependencies: - postcss "^7.0.17" - postcss-values-parser "^2.0.1" - -postcss-custom-selectors@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" - integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-dir-pseudo-class@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" - integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-discard-comments@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" - integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== - dependencies: - postcss "^7.0.0" - -postcss-discard-duplicates@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== - dependencies: - postcss "^7.0.0" - -postcss-discard-empty@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== - dependencies: - postcss "^7.0.0" - -postcss-discard-overridden@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== - dependencies: - postcss "^7.0.0" - -postcss-double-position-gradients@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" - integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== - dependencies: - postcss "^7.0.5" - postcss-values-parser "^2.0.0" - -postcss-env-function@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" - integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-flexbugs-fixes@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz#9218a65249f30897deab1033aced8578562a6690" - integrity sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ== - dependencies: - postcss "^7.0.26" - -postcss-focus-visible@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" - integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== - dependencies: - postcss "^7.0.2" - -postcss-focus-within@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" - integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== - dependencies: - postcss "^7.0.2" - -postcss-font-variant@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz#42d4c0ab30894f60f98b17561eb5c0321f502641" - integrity sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA== - dependencies: - postcss "^7.0.2" - -postcss-gap-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" - integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== - dependencies: - postcss "^7.0.2" - -postcss-image-set-function@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" - integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-import@^12.0.1: - version "12.0.1" - resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-12.0.1.tgz#cf8c7ab0b5ccab5649024536e565f841928b7153" - integrity sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw== - dependencies: - postcss "^7.0.1" - postcss-value-parser "^3.2.3" - read-cache "^1.0.0" - resolve "^1.1.7" - -postcss-initial@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.4.tgz#9d32069a10531fe2ecafa0b6ac750ee0bc7efc53" - integrity sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg== - dependencies: - postcss "^7.0.2" - -postcss-lab-function@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" - integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== - dependencies: - "@csstools/convert-colors" "^1.4.0" - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-load-config@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.2.tgz#c5ea504f2c4aef33c7359a34de3573772ad7502a" - integrity sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw== - dependencies: - cosmiconfig "^5.0.0" - import-cwd "^2.0.0" - -postcss-loader@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" - integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA== - dependencies: - loader-utils "^1.1.0" - postcss "^7.0.0" - postcss-load-config "^2.0.0" - schema-utils "^1.0.0" - -postcss-logical@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" - integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== - dependencies: - postcss "^7.0.2" - -postcss-media-minmax@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" - integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== - dependencies: - postcss "^7.0.2" - -postcss-merge-longhand@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" - integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== - dependencies: - css-color-names "0.0.4" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - stylehacks "^4.0.0" - -postcss-merge-rules@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" - integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - cssnano-util-same-parent "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - vendors "^1.0.0" - -postcss-minify-font-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-gradients@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" - integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - is-color-stop "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-params@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" - integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== - dependencies: - alphanum-sort "^1.0.0" - browserslist "^4.0.0" - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - uniqs "^2.0.0" - -postcss-minify-selectors@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" - integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== - dependencies: - alphanum-sort "^1.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -postcss-modules-extract-imports@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" - integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== - dependencies: - postcss "^7.0.5" - -postcss-modules-local-by-default@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" - integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== - dependencies: - icss-utils "^4.1.1" - postcss "^7.0.32" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" - -postcss-modules-scope@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" - integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== - dependencies: - postcss "^7.0.6" - postcss-selector-parser "^6.0.0" - -postcss-modules-values@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" - integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== - dependencies: - icss-utils "^4.0.0" - postcss "^7.0.6" - -postcss-nesting@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" - integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== - dependencies: - postcss "^7.0.2" - -postcss-normalize-charset@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== - dependencies: - postcss "^7.0.0" - -postcss-normalize-display-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" - integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-positions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" - integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-repeat-style@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" - integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-string@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" - integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== - dependencies: - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-timing-functions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" - integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-unicode@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-url@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== - dependencies: - is-absolute-url "^2.0.0" - normalize-url "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-whitespace@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" - integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-ordered-values@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" - integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== - dependencies: - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-overflow-shorthand@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" - integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== - dependencies: - postcss "^7.0.2" - -postcss-page-break@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" - integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== - dependencies: - postcss "^7.0.2" - -postcss-place@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" - integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== - dependencies: - postcss "^7.0.2" - postcss-values-parser "^2.0.0" - -postcss-preset-env@^6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" - integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg== - dependencies: - autoprefixer "^9.6.1" - browserslist "^4.6.4" - caniuse-lite "^1.0.30000981" - css-blank-pseudo "^0.1.4" - css-has-pseudo "^0.10.0" - css-prefers-color-scheme "^3.1.1" - cssdb "^4.4.0" - postcss "^7.0.17" - postcss-attribute-case-insensitive "^4.0.1" - postcss-color-functional-notation "^2.0.1" - postcss-color-gray "^5.0.0" - postcss-color-hex-alpha "^5.0.3" - postcss-color-mod-function "^3.0.3" - postcss-color-rebeccapurple "^4.0.1" - postcss-custom-media "^7.0.8" - postcss-custom-properties "^8.0.11" - postcss-custom-selectors "^5.1.2" - postcss-dir-pseudo-class "^5.0.0" - postcss-double-position-gradients "^1.0.0" - postcss-env-function "^2.0.2" - postcss-focus-visible "^4.0.0" - postcss-focus-within "^3.0.0" - postcss-font-variant "^4.0.0" - postcss-gap-properties "^2.0.0" - postcss-image-set-function "^3.0.1" - postcss-initial "^3.0.0" - postcss-lab-function "^2.0.1" - postcss-logical "^3.0.0" - postcss-media-minmax "^4.0.0" - postcss-nesting "^7.0.0" - postcss-overflow-shorthand "^2.0.0" - postcss-page-break "^2.0.0" - postcss-place "^4.0.1" - postcss-pseudo-class-any-link "^6.0.0" - postcss-replace-overflow-wrap "^3.0.0" - postcss-selector-matches "^4.0.0" - postcss-selector-not "^4.0.0" - -postcss-pseudo-class-any-link@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" - integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== - dependencies: - postcss "^7.0.2" - postcss-selector-parser "^5.0.0-rc.3" - -postcss-reduce-initial@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" - integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - -postcss-reduce-transforms@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" - integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== - dependencies: - cssnano-util-get-match "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-replace-overflow-wrap@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" - integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== - dependencies: - postcss "^7.0.2" - -postcss-safe-parser@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz#a6d4e48f0f37d9f7c11b2a581bf00f8ba4870b96" - integrity sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g== - dependencies: - postcss "^7.0.26" - -postcss-selector-matches@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" - integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" - -postcss-selector-not@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz#263016eef1cf219e0ade9a913780fc1f48204cbf" - integrity sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ== - dependencies: - balanced-match "^1.0.0" - postcss "^7.0.2" - -postcss-selector-parser@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" - integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== - dependencies: - dot-prop "^5.2.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== - dependencies: - cssesc "^2.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: - version "6.0.6" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea" - integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-svgo@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.3.tgz#343a2cdbac9505d416243d496f724f38894c941e" - integrity sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - svgo "^1.0.0" - -postcss-unique-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== - dependencies: - alphanum-sort "^1.0.0" - postcss "^7.0.0" - uniqs "^2.0.0" - -postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3: - version "3.3.1" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== - -postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" - integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== - -postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" - integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== - dependencies: - flatten "^1.0.2" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.26, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.36" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.36.tgz#056f8cffa939662a8f5905950c07d5285644dfcb" - integrity sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - -postcss@^8.3.6: - version "8.3.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.6.tgz#2730dd76a97969f37f53b9a6096197be311cc4ea" - integrity sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A== - dependencies: - colorette "^1.2.2" - nanoid "^3.1.23" - source-map-js "^0.6.2" - -prepend-http@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= - -proxy-addr@~2.0.5: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.3: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.2.4: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -q@^1.1.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - -query-string@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" - integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= - dependencies: - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - -read-cache@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" - integrity sha1-5mTvMRYRZsl1HNvo28+GtftY93Q= - dependencies: - pify "^2.3.0" - -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== - -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== - dependencies: - "@babel/runtime" "^7.8.4" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexp.prototype.flags@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" - integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -regexpu-core@^4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" - integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" - -regjsgen@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== - -regjsparser@^0.6.4: - version "0.6.9" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.9.tgz#b489eef7c9a2ce43727627011429cf833a7183e6" - integrity sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ== - dependencies: - jsesc "~0.5.0" - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" - integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" - -resolve-dir@^1.0.0, resolve-dir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@^1.1.7, resolve@^1.12.0, resolve@^1.14.2: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= - -rgb-regex@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= - -rgba-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= - -rimraf@^2.5.4, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -run-queue@^1.0.0, run-queue@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= - dependencies: - aproba "^1.1.1" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sass-loader@10.1.1: - version "10.1.1" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.1.1.tgz#4ddd5a3d7638e7949065dd6e9c7c04037f7e663d" - integrity sha512-W6gVDXAd5hR/WHsPicvZdjAWHBcEJ44UahgxcIE196fW2ong0ZHMPO1kZuI5q0VlvMQZh32gpv69PLWQm70qrw== - dependencies: - klona "^2.0.4" - loader-utils "^2.0.0" - neo-async "^2.6.2" - schema-utils "^3.0.0" - semver "^7.3.2" - -sass@^1.32.13: - version "1.37.5" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.37.5.tgz#f6838351f7cc814c4fcfe1d9a20e0cabbd1e7b3c" - integrity sha512-Cx3ewxz9QB/ErnVIiWg2cH0kiYZ0FPvheDTVC6BsiEGBTZKKZJ1Gq5Kq6jy3PKtL6+EJ8NIoaBW/RSd2R6cZOA== - dependencies: - chokidar ">=3.0.0 <4.0.0" - -sax@~1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - -schema-utils@^2.6.5, schema-utils@^2.7.0: - version "2.7.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" - integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== - dependencies: - "@types/json-schema" "^7.0.5" - ajv "^6.12.4" - ajv-keywords "^3.5.2" - -schema-utils@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= - -selfsigned@^1.10.8: - version "1.10.11" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.11.tgz#24929cd906fe0f44b6d01fb23999a739537acbe9" - integrity sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA== - dependencies: - node-forge "^0.10.0" - -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@^5.5.0, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.2: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serialize-javascript@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" - integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== - dependencies: - randombytes "^2.1.0" - -serialize-javascript@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" - integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== - dependencies: - randombytes "^2.1.0" - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== - -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= - dependencies: - is-arrayish "^0.3.1" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -sockjs-client@^1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.1.tgz#256908f6d5adfb94dabbdbd02c66362cca0f9ea6" - integrity sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ== - dependencies: - debug "^3.2.6" - eventsource "^1.0.7" - faye-websocket "^0.11.3" - inherits "^2.0.4" - json3 "^3.3.3" - url-parse "^1.5.1" - -sockjs@^0.3.21: - version "0.3.21" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" - integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== - dependencies: - faye-websocket "^0.11.3" - uuid "^3.4.0" - websocket-driver "^0.7.4" - -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= - dependencies: - is-plain-obj "^1.0.0" - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-js@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" - integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== - -source-map-resolve@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" - integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@~0.5.12, source-map-support@~0.5.19: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" - integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== - -source-map@^0.5.0, source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - -spark-md5@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.1.tgz#83a0e255734f2ab4e5c466e5a2cfc9ba2aa2124d" - integrity sha512-0tF3AGSD1ppQeuffsLDIOWlKUd3lS92tFxcsrh5Pe3ZphhnoK+oXIBTzOAThZCiuINZLvpiLH/1VS1/ANEJVig== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -ssri@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" - integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== - dependencies: - figgy-pudding "^3.5.1" - -ssri@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" - integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== - dependencies: - minipass "^3.1.1" - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -stimulus@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/stimulus/-/stimulus-2.0.0.tgz#713c8b91a72ef90914b90955f0e705f004403047" - integrity sha512-xipy7BS5TVpg4fX6S8LhrYZp7cmHGjmk09WSAiVx1gF5S5g43IWsuetfUhIk8HfHUG+4MQ9nY0FQz4dRFLs/8w== - dependencies: - "@stimulus/core" "^2.0.0" - "@stimulus/webpack-helpers" "^2.0.0" - -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-each@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" - integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== - dependencies: - end-of-stream "^1.1.0" - stream-shift "^1.0.0" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-shift@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" - integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string_decoder@^1.0.0, string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -style-loader@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" - integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q== - dependencies: - loader-utils "^2.0.0" - schema-utils "^2.7.0" - -stylehacks@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" - integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -svgo@^1.0.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" - integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== - dependencies: - chalk "^2.4.1" - coa "^2.0.2" - css-select "^2.0.0" - css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.37" - csso "^4.0.2" - js-yaml "^3.13.1" - mkdirp "~0.5.1" - object.values "^1.1.0" - sax "~1.2.4" - stable "^0.1.8" - unquote "~1.1.1" - util.promisify "~1.0.0" - -tapable@^1.0.0, tapable@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tar@^6.0.2: - version "6.1.11" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" - integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^3.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - -terser-webpack-plugin@^1.4.3: - version "1.4.5" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" - integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== - dependencies: - cacache "^12.0.2" - find-cache-dir "^2.1.0" - is-wsl "^1.1.0" - schema-utils "^1.0.0" - serialize-javascript "^4.0.0" - source-map "^0.6.1" - terser "^4.1.2" - webpack-sources "^1.4.0" - worker-farm "^1.7.0" - -terser-webpack-plugin@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz#28daef4a83bd17c1db0297070adc07fc8cfc6a9a" - integrity sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ== - dependencies: - cacache "^15.0.5" - find-cache-dir "^3.3.1" - jest-worker "^26.5.0" - p-limit "^3.0.2" - schema-utils "^3.0.0" - serialize-javascript "^5.0.1" - source-map "^0.6.1" - terser "^5.3.4" - webpack-sources "^1.4.3" - -terser@^4.1.2: - version "4.8.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" - integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - -terser@^5.3.4: - version "5.7.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.7.1.tgz#2dc7a61009b66bb638305cb2a824763b116bf784" - integrity sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg== - dependencies: - commander "^2.20.0" - source-map "~0.7.2" - source-map-support "~0.5.19" - -through2@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -timers-browserify@^2.0.4: - version "2.0.12" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" - integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== - dependencies: - setimmediate "^1.0.4" - -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -trix@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/trix/-/trix-1.3.1.tgz#ccce8d9e72bf0fe70c8c019ff558c70266f8d857" - integrity sha512-BbH6mb6gk+AV4f2as38mP6Ucc1LE3OD6XxkZnAgPIduWXYtvg2mI3cZhIZSLqmMh9OITEpOBCCk88IVmyjU7bA== - -ts-pnp@^1.1.6: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" - integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== - -tslib@^1.9.3: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== - dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" - -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" - integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= - -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-parse@^1.4.3, url-parse@^1.5.1: - version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util.promisify@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" - integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.2" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.0" - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^3.3.2, uuid@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -v8-compile-cache@^2.1.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" - integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vendors@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" - integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== - -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - -watchpack-chokidar2@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" - integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== - dependencies: - chokidar "^2.1.8" - -watchpack@^1.7.4: - version "1.7.5" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" - integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== - dependencies: - graceful-fs "^4.1.2" - neo-async "^2.5.0" - optionalDependencies: - chokidar "^3.4.1" - watchpack-chokidar2 "^2.0.1" - -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -webpack-assets-manifest@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/webpack-assets-manifest/-/webpack-assets-manifest-3.1.1.tgz#39bbc3bf2ee57fcd8ba07cda51c9ba4a3c6ae1de" - integrity sha512-JV9V2QKc5wEWQptdIjvXDUL1ucbPLH2f27toAY3SNdGZp+xSaStAgpoMcvMZmqtFrBc9a5pTS1058vxyMPOzRQ== - dependencies: - chalk "^2.0" - lodash.get "^4.0" - lodash.has "^4.0" - mkdirp "^0.5" - schema-utils "^1.0.0" - tapable "^1.0.0" - webpack-sources "^1.0.0" - -webpack-cli@^3.3.12: - version "3.3.12" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" - integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag== - dependencies: - chalk "^2.4.2" - cross-spawn "^6.0.5" - enhanced-resolve "^4.1.1" - findup-sync "^3.0.0" - global-modules "^2.0.0" - import-local "^2.0.0" - interpret "^1.4.0" - loader-utils "^1.4.0" - supports-color "^6.1.0" - v8-compile-cache "^2.1.1" - yargs "^13.3.2" - -webpack-dev-middleware@^3.7.2: - version "3.7.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" - integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== - dependencies: - memory-fs "^0.4.1" - mime "^2.4.4" - mkdirp "^0.5.1" - range-parser "^1.2.1" - webpack-log "^2.0.0" - -webpack-dev-server@^3.11.2: - version "3.11.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708" - integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ== - dependencies: - ansi-html "0.0.7" - bonjour "^3.5.0" - chokidar "^2.1.8" - compression "^1.7.4" - connect-history-api-fallback "^1.6.0" - debug "^4.1.1" - del "^4.1.1" - express "^4.17.1" - html-entities "^1.3.1" - http-proxy-middleware "0.19.1" - import-local "^2.0.0" - internal-ip "^4.3.0" - ip "^1.1.5" - is-absolute-url "^3.0.3" - killable "^1.0.1" - loglevel "^1.6.8" - opn "^5.5.0" - p-retry "^3.0.1" - portfinder "^1.0.26" - schema-utils "^1.0.0" - selfsigned "^1.10.8" - semver "^6.3.0" - serve-index "^1.9.1" - sockjs "^0.3.21" - sockjs-client "^1.5.0" - spdy "^4.0.2" - strip-ansi "^3.0.1" - supports-color "^6.1.0" - url "^0.11.0" - webpack-dev-middleware "^3.7.2" - webpack-log "^2.0.0" - ws "^6.2.1" - yargs "^13.3.2" - -webpack-log@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" - integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== - dependencies: - ansi-colors "^3.0.0" - uuid "^3.3.2" - -webpack-sources@^1.0.0, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack@^4.46.0: - version "4.46.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" - integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/wasm-edit" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - acorn "^6.4.1" - ajv "^6.10.2" - ajv-keywords "^3.4.1" - chrome-trace-event "^1.0.2" - enhanced-resolve "^4.5.0" - eslint-scope "^4.0.3" - json-parse-better-errors "^1.0.2" - loader-runner "^2.4.0" - loader-utils "^1.2.3" - memory-fs "^0.4.1" - micromatch "^3.1.10" - mkdirp "^0.5.3" - neo-async "^2.6.1" - node-libs-browser "^2.2.1" - schema-utils "^1.0.0" - tapable "^1.1.3" - terser-webpack-plugin "^1.4.3" - watchpack "^1.7.4" - webpack-sources "^1.4.1" - -websocket-driver@>=0.5.1, websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@^1.2.14, which@^1.2.9, which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -worker-farm@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" - integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== - dependencies: - errno "~0.1.7" - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -ws@^6.2.1: - version "6.2.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e" - integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw== - dependencies: - async-limiter "~1.0.0" - -xtend@^4.0.0, xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.7.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" - integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== - -yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs@^13.3.2: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 494aa9562176fb0bcf52967114302eec36140070 Mon Sep 17 00:00:00 2001 From: Justin Adkins Date: Mon, 15 Jan 2024 01:49:05 -0500 Subject: [PATCH 02/24] Rails 7.1 new --- .dockerignore | 37 ++ .gitattributes | 9 + .gitignore | 35 ++ .ruby-version | 1 + Dockerfile | 62 ++++ Gemfile | 36 ++ Gemfile.lock | 320 ++++++++++++++++++ README.md | 24 ++ Rakefile | 6 + app/assets/images/.keep | 0 app/assets/stylesheets/application.css | 1 + app/channels/application_cable/channel.rb | 4 + app/channels/application_cable/connection.rb | 4 + app/controllers/application_controller.rb | 2 + app/controllers/concerns/.keep | 0 app/helpers/application_helper.rb | 2 + app/javascript/application.js | 3 + app/javascript/controllers/application.js | 9 + .../controllers/hello_controller.js | 7 + app/javascript/controllers/index.js | 11 + app/jobs/application_job.rb | 7 + app/mailers/application_mailer.rb | 4 + app/models/application_record.rb | 3 + app/models/concerns/.keep | 0 app/views/layouts/application.html.erb | 16 + app/views/layouts/mailer.html.erb | 13 + app/views/layouts/mailer.text.erb | 1 + bin/bundle | 109 ++++++ bin/docker-entrypoint | 8 + bin/importmap | 4 + bin/rails | 4 + bin/rake | 4 + bin/setup | 33 ++ config.ru | 6 + config/application.rb | 39 +++ config/boot.rb | 4 + config/cable.yml | 10 + config/credentials.yml.enc | 1 + config/database.yml | 25 ++ config/environment.rb | 5 + config/environments/development.rb | 75 ++++ config/environments/production.rb | 91 +++++ config/environments/test.rb | 64 ++++ config/importmap.rb | 7 + config/initializers/assets.rb | 7 + .../initializers/content_security_policy.rb | 25 ++ .../initializers/filter_parameter_logging.rb | 8 + config/initializers/inflections.rb | 16 + config/initializers/permissions_policy.rb | 13 + config/locales/en.yml | 31 ++ config/puma.rb | 35 ++ config/routes.rb | 10 + config/storage.yml | 34 ++ db/schema.rb | 14 + db/seeds.rb | 9 + dev/mythcoders.test.crt | 26 ++ dev/mythcoders.test.key | 28 ++ dev/nginx.conf | 43 +++ dev/rules.yml | 6 + dev/setup.yml | 152 +++++++++ docker-compose.yml | 59 ++++ lib/assets/.keep | 0 lib/email_helper.rb | 15 + lib/tasks/.keep | 0 lib/tasks/auto_annotate_models.rake | 59 ++++ log/.keep | 0 public/404.html | 67 ++++ public/422.html | 67 ++++ public/500.html | 66 ++++ public/apple-touch-icon-precomposed.png | 0 public/apple-touch-icon.png | 0 public/favicon.ico | 0 public/robots.txt | 1 + storage/.keep | 0 test/application_system_test_case.rb | 5 + .../application_cable/connection_test.rb | 13 + test/controllers/.keep | 0 test/fixtures/files/.keep | 0 test/helpers/.keep | 0 test/integration/.keep | 0 test/mailers/.keep | 0 test/models/.keep | 0 test/system/.keep | 0 test/test_helper.rb | 15 + tmp/.keep | 0 tmp/pids/.keep | 0 tmp/storage/.keep | 0 vendor/.keep | 0 vendor/javascript/.keep | 0 89 files changed, 1930 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .ruby-version create mode 100644 Dockerfile create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 README.md create mode 100644 Rakefile create mode 100644 app/assets/images/.keep create mode 100644 app/assets/stylesheets/application.css create mode 100644 app/channels/application_cable/channel.rb create mode 100644 app/channels/application_cable/connection.rb create mode 100644 app/controllers/application_controller.rb create mode 100644 app/controllers/concerns/.keep create mode 100644 app/helpers/application_helper.rb create mode 100644 app/javascript/application.js create mode 100644 app/javascript/controllers/application.js create mode 100644 app/javascript/controllers/hello_controller.js create mode 100644 app/javascript/controllers/index.js create mode 100644 app/jobs/application_job.rb create mode 100644 app/mailers/application_mailer.rb create mode 100644 app/models/application_record.rb create mode 100644 app/models/concerns/.keep create mode 100644 app/views/layouts/application.html.erb create mode 100644 app/views/layouts/mailer.html.erb create mode 100644 app/views/layouts/mailer.text.erb create mode 100755 bin/bundle create mode 100755 bin/docker-entrypoint create mode 100755 bin/importmap create mode 100755 bin/rails create mode 100755 bin/rake create mode 100755 bin/setup create mode 100644 config.ru create mode 100644 config/application.rb create mode 100644 config/boot.rb create mode 100644 config/cable.yml create mode 100644 config/credentials.yml.enc create mode 100644 config/database.yml create mode 100644 config/environment.rb create mode 100644 config/environments/development.rb create mode 100644 config/environments/production.rb create mode 100644 config/environments/test.rb create mode 100644 config/importmap.rb create mode 100644 config/initializers/assets.rb create mode 100644 config/initializers/content_security_policy.rb create mode 100644 config/initializers/filter_parameter_logging.rb create mode 100644 config/initializers/inflections.rb create mode 100644 config/initializers/permissions_policy.rb create mode 100644 config/locales/en.yml create mode 100644 config/puma.rb create mode 100644 config/routes.rb create mode 100644 config/storage.yml create mode 100644 db/schema.rb create mode 100644 db/seeds.rb create mode 100644 dev/mythcoders.test.crt create mode 100644 dev/mythcoders.test.key create mode 100644 dev/nginx.conf create mode 100644 dev/rules.yml create mode 100644 dev/setup.yml create mode 100644 docker-compose.yml create mode 100644 lib/assets/.keep create mode 100644 lib/email_helper.rb create mode 100644 lib/tasks/.keep create mode 100644 lib/tasks/auto_annotate_models.rake create mode 100644 log/.keep create mode 100644 public/404.html create mode 100644 public/422.html create mode 100644 public/500.html create mode 100644 public/apple-touch-icon-precomposed.png create mode 100644 public/apple-touch-icon.png create mode 100644 public/favicon.ico create mode 100644 public/robots.txt create mode 100644 storage/.keep create mode 100644 test/application_system_test_case.rb create mode 100644 test/channels/application_cable/connection_test.rb create mode 100644 test/controllers/.keep create mode 100644 test/fixtures/files/.keep create mode 100644 test/helpers/.keep create mode 100644 test/integration/.keep create mode 100644 test/mailers/.keep create mode 100644 test/models/.keep create mode 100644 test/system/.keep create mode 100644 test/test_helper.rb create mode 100644 tmp/.keep create mode 100644 tmp/pids/.keep create mode 100644 tmp/storage/.keep create mode 100644 vendor/.keep create mode 100644 vendor/javascript/.keep diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9612375 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,37 @@ +# See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files. + +# Ignore git directory. +/.git/ + +# Ignore bundler config. +/.bundle + +# Ignore all environment files (except templates). +/.env* +!/.env*.erb + +# Ignore all default key files. +/config/master.key +/config/credentials/*.key + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +# Ignore pidfiles, but keep the directory. +/tmp/pids/* +!/tmp/pids/.keep + +# Ignore storage (uploaded files in development and any SQLite databases). +/storage/* +!/storage/.keep +/tmp/storage/* +!/tmp/storage/.keep + +# Ignore assets. +/node_modules/ +/app/assets/builds/* +!/app/assets/builds/.keep +/public/assets diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8dc4323 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +# See https://git-scm.com/docs/gitattributes for more about git attribute files. + +# Mark the database schema as having been generated. +db/schema.rb linguist-generated + +# Mark any vendored files as having been vendored. +vendor/* linguist-vendored +config/credentials/*.yml.enc diff=rails_credentials +config/credentials.yml.enc diff=rails_credentials diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5fb66c9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# Ignore all environment files (except templates). +/.env* +!/.env*.erb + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +# Ignore pidfiles, but keep the directory. +/tmp/pids/* +!/tmp/pids/ +!/tmp/pids/.keep + +# Ignore storage (uploaded files in development and any SQLite databases). +/storage/* +!/storage/.keep +/tmp/storage/* +!/tmp/storage/ +!/tmp/storage/.keep + +/public/assets + +# Ignore master key for decrypting credentials and more. +/config/master.key diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..be94e6f --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.2.2 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..498898d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,62 @@ +# syntax = docker/dockerfile:1 + +# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile +ARG RUBY_VERSION=3.2.2 +FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base + +# Rails app lives here +WORKDIR /rails + +# Set production environment +ENV RAILS_ENV="production" \ + BUNDLE_DEPLOYMENT="1" \ + BUNDLE_PATH="/usr/local/bundle" \ + BUNDLE_WITHOUT="development" + + +# Throw-away build stage to reduce size of final image +FROM base as build + +# Install packages needed to build gems +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y build-essential git libvips pkg-config + +# Install application gems +COPY Gemfile Gemfile.lock ./ +RUN bundle install && \ + rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \ + bundle exec bootsnap precompile --gemfile + +# Copy application code +COPY . . + +# Precompile bootsnap code for faster boot times +RUN bundle exec bootsnap precompile app/ lib/ + +# Precompiling assets for production without requiring secret RAILS_MASTER_KEY +RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile + +# Entrypoint prepares the database. +ENTRYPOINT ["/rails/bin/docker-entrypoint"] + +EXPOSE 3000 + +# Final stage for app image +FROM base + +# Install packages needed for deployment +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y curl libsqlite3-0 libvips && \ + rm -rf /var/lib/apt/lists /var/cache/apt/archives + +# Copy built artifacts: gems, application +COPY --from=build /usr/local/bundle /usr/local/bundle +COPY --from=build /rails /rails + +# Run and own only the runtime files as a non-root user for security +RUN useradd rails --create-home --shell /bin/bash && \ + chown -R rails:rails db log storage tmp +USER rails:rails + +# Start the server by default, this can be overwritten at runtime +CMD ["./bin/rails", "server"] diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..5bf31f7 --- /dev/null +++ b/Gemfile @@ -0,0 +1,36 @@ +source "https://rubygems.org" + +ruby "3.2.2" + +gem "rails", "~> 7.1" + +gem "bcrypt" +gem "bootsnap", require: false +gem "importmap-rails" +gem "propshaft" +gem "puma", ">= 5.0" +gem "solid_queue" +gem "sqlite3", "~> 1.4" +gem "stimulus-rails" +gem "turbo-rails" +gem "tzinfo-data", platforms: %i[ windows jruby ] +gem "view_component" + +# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] +# gem "image_processing", "~> 1.2" + +group :development, :test do + gem "annotate" + gem "debug", platforms: %i[ mri windows ] + gem "dotenv-rails" + gem "standard" +end + +group :development do + gem "web-console" +end + +group :test do + gem "capybara" + gem "selenium-webdriver" +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..f1a6c46 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,320 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.1.2) + actionpack (= 7.1.2) + activesupport (= 7.1.2) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + zeitwerk (~> 2.6) + actionmailbox (7.1.2) + actionpack (= 7.1.2) + activejob (= 7.1.2) + activerecord (= 7.1.2) + activestorage (= 7.1.2) + activesupport (= 7.1.2) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.1.2) + actionpack (= 7.1.2) + actionview (= 7.1.2) + activejob (= 7.1.2) + activesupport (= 7.1.2) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.2) + actionpack (7.1.2) + actionview (= 7.1.2) + activesupport (= 7.1.2) + nokogiri (>= 1.8.5) + racc + rack (>= 2.2.4) + rack-session (>= 1.0.1) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + actiontext (7.1.2) + actionpack (= 7.1.2) + activerecord (= 7.1.2) + activestorage (= 7.1.2) + activesupport (= 7.1.2) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.1.2) + activesupport (= 7.1.2) + builder (~> 3.1) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activejob (7.1.2) + activesupport (= 7.1.2) + globalid (>= 0.3.6) + activemodel (7.1.2) + activesupport (= 7.1.2) + activerecord (7.1.2) + activemodel (= 7.1.2) + activesupport (= 7.1.2) + timeout (>= 0.4.0) + activestorage (7.1.2) + actionpack (= 7.1.2) + activejob (= 7.1.2) + activerecord (= 7.1.2) + activesupport (= 7.1.2) + marcel (~> 1.0) + activesupport (7.1.2) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + minitest (>= 5.1) + mutex_m + tzinfo (~> 2.0) + addressable (2.8.6) + public_suffix (>= 2.0.2, < 6.0) + annotate (3.2.0) + activerecord (>= 3.2, < 8.0) + rake (>= 10.4, < 14.0) + ast (2.4.2) + base64 (0.2.0) + bcrypt (3.1.20) + bigdecimal (3.1.5) + bindex (0.8.1) + bootsnap (1.17.1) + msgpack (~> 1.2) + builder (3.2.4) + capybara (3.39.2) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + concurrent-ruby (1.2.2) + connection_pool (2.4.1) + crass (1.0.6) + date (3.3.4) + debug (1.9.1) + irb (~> 1.10) + reline (>= 0.3.8) + dotenv (2.8.1) + dotenv-rails (2.8.1) + dotenv (= 2.8.1) + railties (>= 3.2) + drb (2.2.0) + ruby2_keywords + erubi (1.12.0) + globalid (1.2.1) + activesupport (>= 6.1) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + importmap-rails (2.0.1) + actionpack (>= 6.0.0) + activesupport (>= 6.0.0) + railties (>= 6.0.0) + io-console (0.7.1) + irb (1.11.1) + rdoc + reline (>= 0.4.2) + json (2.7.1) + language_server-protocol (3.17.0.3) + lint_roller (1.1.0) + loofah (2.22.0) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.8.1) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.0.2) + matrix (0.4.2) + method_source (1.0.0) + mini_mime (1.1.5) + minitest (5.21.1) + msgpack (1.7.2) + mutex_m (0.2.0) + net-imap (0.4.9.1) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.4.0.1) + net-protocol + nio4r (2.7.0) + nokogiri (1.16.0-aarch64-linux) + racc (~> 1.4) + nokogiri (1.16.0-arm64-darwin) + racc (~> 1.4) + nokogiri (1.16.0-x86_64-linux) + racc (~> 1.4) + parallel (1.24.0) + parser (3.3.0.3) + ast (~> 2.4.1) + racc + propshaft (0.8.0) + actionpack (>= 7.0.0) + activesupport (>= 7.0.0) + rack + railties (>= 7.0.0) + psych (5.1.2) + stringio + public_suffix (5.0.4) + puma (6.4.2) + nio4r (~> 2.0) + racc (1.7.3) + rack (3.0.8) + rack-session (2.0.0) + rack (>= 3.0.0) + rack-test (2.1.0) + rack (>= 1.3) + rackup (2.1.0) + rack (>= 3) + webrick (~> 1.8) + rails (7.1.2) + actioncable (= 7.1.2) + actionmailbox (= 7.1.2) + actionmailer (= 7.1.2) + actionpack (= 7.1.2) + actiontext (= 7.1.2) + actionview (= 7.1.2) + activejob (= 7.1.2) + activemodel (= 7.1.2) + activerecord (= 7.1.2) + activestorage (= 7.1.2) + activesupport (= 7.1.2) + bundler (>= 1.15.0) + railties (= 7.1.2) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (7.1.2) + actionpack (= 7.1.2) + activesupport (= 7.1.2) + irb + rackup (>= 1.0.0) + rake (>= 12.2) + thor (~> 1.0, >= 1.2.2) + zeitwerk (~> 2.6) + rainbow (3.1.1) + rake (13.1.0) + rdoc (6.6.2) + psych (>= 4.0.0) + regexp_parser (2.9.0) + reline (0.4.2) + io-console (~> 0.5) + rexml (3.2.6) + rubocop (1.59.0) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.2.2.4) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.30.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.30.0) + parser (>= 3.2.1.0) + rubocop-performance (1.20.2) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.30.0, < 2.0) + ruby-progressbar (1.13.0) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + selenium-webdriver (4.16.0) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + solid_queue (0.1.2) + rails (>= 7.0.3.1) + sqlite3 (1.7.0-aarch64-linux) + sqlite3 (1.7.0-arm64-darwin) + sqlite3 (1.7.0-x86_64-linux) + standard (1.33.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.59.0) + standard-custom (~> 1.0.0) + standard-performance (~> 1.3) + standard-custom (1.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.50) + standard-performance (1.3.1) + lint_roller (~> 1.1) + rubocop-performance (~> 1.20.2) + stimulus-rails (1.3.3) + railties (>= 6.0.0) + stringio (3.1.0) + thor (1.3.0) + timeout (0.4.1) + turbo-rails (1.5.0) + actionpack (>= 6.0.0) + activejob (>= 6.0.0) + railties (>= 6.0.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + unicode-display_width (2.5.0) + view_component (3.10.0) + activesupport (>= 5.2.0, < 8.0) + concurrent-ruby (~> 1.0) + method_source (~> 1.0) + web-console (4.2.1) + actionview (>= 6.0.0) + activemodel (>= 6.0.0) + bindex (>= 0.4.0) + railties (>= 6.0.0) + webrick (1.8.1) + websocket (1.2.10) + websocket-driver (0.7.6) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + xpath (3.2.0) + nokogiri (~> 1.8) + zeitwerk (2.6.12) + +PLATFORMS + aarch64-linux + arm64-darwin-23 + x86_64-linux + +DEPENDENCIES + annotate + bcrypt + bootsnap + capybara + debug + dotenv-rails + importmap-rails + propshaft + puma (>= 5.0) + rails (~> 7.1) + selenium-webdriver + solid_queue + sqlite3 (~> 1.4) + standard + stimulus-rails + turbo-rails + tzinfo-data + view_component + web-console + +RUBY VERSION + ruby 3.2.2p53 + +BUNDLED WITH + 2.4.19 diff --git a/README.md b/README.md new file mode 100644 index 0000000..7db80e4 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# README + +This README would normally document whatever steps are necessary to get the +application up and running. + +Things you may want to cover: + +* Ruby version + +* System dependencies + +* Configuration + +* Database creation + +* Database initialization + +* How to run the test suite + +* Services (job queues, cache servers, search engines, etc.) + +* Deployment instructions + +* ... diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..9a5ea73 --- /dev/null +++ b/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative "config/application" + +Rails.application.load_tasks diff --git a/app/assets/images/.keep b/app/assets/images/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 0000000..dcd7273 --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1 @@ +/* Application styles */ diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb new file mode 100644 index 0000000..d672697 --- /dev/null +++ b/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb new file mode 100644 index 0000000..0ff5442 --- /dev/null +++ b/app/channels/application_cable/connection.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 index 0000000..09705d1 --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,2 @@ +class ApplicationController < ActionController::Base +end diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000..de6be79 --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/app/javascript/application.js b/app/javascript/application.js new file mode 100644 index 0000000..0d7b494 --- /dev/null +++ b/app/javascript/application.js @@ -0,0 +1,3 @@ +// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails +import "@hotwired/turbo-rails" +import "controllers" diff --git a/app/javascript/controllers/application.js b/app/javascript/controllers/application.js new file mode 100644 index 0000000..1213e85 --- /dev/null +++ b/app/javascript/controllers/application.js @@ -0,0 +1,9 @@ +import { Application } from "@hotwired/stimulus" + +const application = Application.start() + +// Configure Stimulus development experience +application.debug = false +window.Stimulus = application + +export { application } diff --git a/app/javascript/controllers/hello_controller.js b/app/javascript/controllers/hello_controller.js new file mode 100644 index 0000000..5975c07 --- /dev/null +++ b/app/javascript/controllers/hello_controller.js @@ -0,0 +1,7 @@ +import { Controller } from "@hotwired/stimulus" + +export default class extends Controller { + connect() { + this.element.textContent = "Hello World!" + } +} diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js new file mode 100644 index 0000000..54ad4ca --- /dev/null +++ b/app/javascript/controllers/index.js @@ -0,0 +1,11 @@ +// Import and register all your controllers from the importmap under controllers/* + +import { application } from "controllers/application" + +// Eager load all controllers defined in the import map under controllers/**/*_controller +import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading" +eagerLoadControllersFrom("controllers", application) + +// Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!) +// import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading" +// lazyLoadControllersFrom("controllers", application) diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb new file mode 100644 index 0000000..d394c3d --- /dev/null +++ b/app/jobs/application_job.rb @@ -0,0 +1,7 @@ +class ApplicationJob < ActiveJob::Base + # Automatically retry jobs that encountered a deadlock + # retry_on ActiveRecord::Deadlocked + + # Most jobs are safe to ignore if the underlying records are no longer available + # discard_on ActiveJob::DeserializationError +end diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb new file mode 100644 index 0000000..3c34c81 --- /dev/null +++ b/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: "from@example.com" + layout "mailer" +end diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 0000000..b63caeb --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + primary_abstract_class +end diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 0000000..d0dc47d --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,16 @@ + + + + Hermes + + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + + <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> + <%= javascript_importmap_tags %> + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 0000000..3aac900 --- /dev/null +++ b/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb new file mode 100644 index 0000000..37f0bdd --- /dev/null +++ b/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 0000000..42c7fd7 --- /dev/null +++ b/bin/bundle @@ -0,0 +1,109 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'bundle' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "rubygems" + +m = Module.new do + module_function + + def invoked_as_script? + File.expand_path($0) == File.expand_path(__FILE__) + end + + def env_var_version + ENV["BUNDLER_VERSION"] + end + + def cli_arg_version + return unless invoked_as_script? # don't want to hijack other binstubs + return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` + bundler_version = nil + update_index = nil + ARGV.each_with_index do |a, i| + if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN + bundler_version = a + end + next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ + bundler_version = $1 + update_index = i + end + bundler_version + end + + def gemfile + gemfile = ENV["BUNDLE_GEMFILE"] + return gemfile if gemfile && !gemfile.empty? + + File.expand_path("../Gemfile", __dir__) + end + + def lockfile + lockfile = + case File.basename(gemfile) + when "gems.rb" then gemfile.sub(/\.rb$/, ".locked") + else "#{gemfile}.lock" + end + File.expand_path(lockfile) + end + + def lockfile_version + return unless File.file?(lockfile) + lockfile_contents = File.read(lockfile) + return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ + Regexp.last_match(1) + end + + def bundler_requirement + @bundler_requirement ||= + env_var_version || + cli_arg_version || + bundler_requirement_for(lockfile_version) + end + + def bundler_requirement_for(version) + return "#{Gem::Requirement.default}.a" unless version + + bundler_gem_version = Gem::Version.new(version) + + bundler_gem_version.approximate_recommendation + end + + def load_bundler! + ENV["BUNDLE_GEMFILE"] ||= gemfile + + activate_bundler + end + + def activate_bundler + gem_error = activation_error_handling do + gem "bundler", bundler_requirement + end + return if gem_error.nil? + require_error = activation_error_handling do + require "bundler/version" + end + return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) + warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" + exit 42 + end + + def activation_error_handling + yield + nil + rescue StandardError, LoadError => e + e + end +end + +m.load_bundler! + +if m.invoked_as_script? + load Gem.bin_path("bundler", "bundle") +end diff --git a/bin/docker-entrypoint b/bin/docker-entrypoint new file mode 100755 index 0000000..67ef493 --- /dev/null +++ b/bin/docker-entrypoint @@ -0,0 +1,8 @@ +#!/bin/bash -e + +# If running the rails server then create or migrate existing database +if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]; then + ./bin/rails db:prepare +fi + +exec "${@}" diff --git a/bin/importmap b/bin/importmap new file mode 100755 index 0000000..36502ab --- /dev/null +++ b/bin/importmap @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby + +require_relative "../config/application" +require "importmap/commands" diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000..efc0377 --- /dev/null +++ b/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path("../config/application", __dir__) +require_relative "../config/boot" +require "rails/commands" diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000..4fbf10b --- /dev/null +++ b/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative "../config/boot" +require "rake" +Rake.application.run diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000..3cd5a9d --- /dev/null +++ b/bin/setup @@ -0,0 +1,33 @@ +#!/usr/bin/env ruby +require "fileutils" + +# path to your application root. +APP_ROOT = File.expand_path("..", __dir__) + +def system!(*args) + system(*args, exception: true) +end + +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. + # Add necessary setup steps to this file. + + puts "== Installing dependencies ==" + system! "gem install bundler --conservative" + system("bundle check") || system!("bundle install") + + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # FileUtils.cp "config/database.yml.sample", "config/database.yml" + # end + + puts "\n== Preparing database ==" + system! "bin/rails db:prepare" + + puts "\n== Removing old logs and tempfiles ==" + system! "bin/rails log:clear tmp:clear" + + puts "\n== Restarting application server ==" + system! "bin/rails restart" +end diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..4a3c09a --- /dev/null +++ b/config.ru @@ -0,0 +1,6 @@ +# This file is used by Rack-based servers to start the application. + +require_relative "config/environment" + +run Rails.application +Rails.application.load_server diff --git a/config/application.rb b/config/application.rb new file mode 100644 index 0000000..71a170c --- /dev/null +++ b/config/application.rb @@ -0,0 +1,39 @@ +require_relative "boot" + +require "rails" +# Pick the frameworks you want: +require "active_model/railtie" +require "active_job/railtie" +require "active_record/railtie" +require "active_storage/engine" +require "action_controller/railtie" +require "action_mailer/railtie" +# require "action_mailbox/engine" +require "action_text/engine" +require "action_view/railtie" +require "action_cable/engine" +require "rails/test_unit/railtie" + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module Hermes + class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 7.1 + + # Please, add to the `ignore` list any other `lib` subdirectories that do + # not contain `.rb` files, or that should not be reloaded or eager loaded. + # Common ones are `templates`, `generators`, or `middleware`, for example. + config.autoload_lib(ignore: %w(assets tasks)) + + # Configuration for the application, engines, and railties goes here. + # + # These settings can be overridden in specific environments using the files + # in config/environments, which are processed later. + # + # config.time_zone = "Central Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 0000000..988a5dd --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,4 @@ +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "bundler/setup" # Set up gems listed in the Gemfile. +require "bootsnap/setup" # Speed up boot time by caching expensive operations. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 0000000..3148f58 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: test + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: hermes_production diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc new file mode 100644 index 0000000..632cdb0 --- /dev/null +++ b/config/credentials.yml.enc @@ -0,0 +1 @@ +hWUoir6sawOIqpseQHn+TBgp/PhfIFw+Bv4MPHRkBKHVAS8/f0JDwDaCx+EUohLenXVgs5ovXb/6CkE1RC/5FHEdtMRa58DqwU3xheglkQ2tQvPQ/20KtiNjnO+Clf4hovVMwH+0KqKFXdELxuQHqAu0muXjw0Dzi0ZdA0jMeEmxbxTVggoRygpwroNNfrOcxKYWd1zZibBq0NDKVFHn9nr+dKSC3NTq2HswfMgsTgVia27M5paTyRV7a8A/r9GGM/0mOrqaLEE7lFLbdKqVlL3+djyMxo/y3pj+8iBBPsgM/WX0YHxg0GMfSF7BRt5L7w/oKdVpdxdz3l5DOgY+1Fe8r3UsanwX7hZEda8KIAiqodsEepa7wd1lh8YCA2x0hvWUqcRgmx2af+qRIRVYe7y72GlC--v+gk1dQMsI66MUt3--ex97lsm2KWiX68X4vEIzzA== \ No newline at end of file diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 0000000..796466b --- /dev/null +++ b/config/database.yml @@ -0,0 +1,25 @@ +# SQLite. Versions 3.8.0 and up are supported. +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem "sqlite3" +# +default: &default + adapter: sqlite3 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + timeout: 5000 + +development: + <<: *default + database: storage/development.sqlite3 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: storage/test.sqlite3 + +production: + <<: *default + database: storage/production.sqlite3 diff --git a/config/environment.rb b/config/environment.rb new file mode 100644 index 0000000..cac5315 --- /dev/null +++ b/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative "application" + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb new file mode 100644 index 0000000..37a383a --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,75 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + config.hosts << "hermes.mythcoders.test" + + # In the development environment your application's code is reloaded any time + # it changes. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.enable_reloading = true + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable server timing + config.server_timing = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join("tmp/caching-dev.txt").exist? + config.action_controller.perform_caching = true + config.action_controller.enable_fragment_cache_logging = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + "Cache-Control" => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options). + config.active_storage.service = :local + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # Highlight code that enqueued background job in logs. + config.active_job.verbose_enqueue_logs = true + + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true + + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true + + # Raise error when a before_action's only/except options reference missing actions + config.action_controller.raise_on_missing_callback_actions = true +end diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 0000000..077936a --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,91 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.enable_reloading = false + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment + # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead. + # config.public_file_server.enabled = false + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.asset_host = "http://assets.example.com" + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache + # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX + + # Store uploaded files on the local file system (see config/storage.yml for options). + config.active_storage.service = :local + + # Mount Action Cable outside main process or domain. + # config.action_cable.mount_path = nil + # config.action_cable.url = "wss://example.com/cable" + # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] + + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + # Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies. + # config.assume_ssl = true + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + config.force_ssl = true + + # Log to STDOUT by default + config.logger = ActiveSupport::Logger.new(STDOUT) + .tap { |logger| logger.formatter = ::Logger::Formatter.new } + .then { |logger| ActiveSupport::TaggedLogging.new(logger) } + + # Prepend all log lines with the following tags. + config.log_tags = [ :request_id ] + + # Info include generic and useful information about system operation, but avoids logging too much + # information to avoid inadvertent exposure of personally identifiable information (PII). If you + # want to log everything, set the level to "debug". + config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment). + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "hermes_production" + + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Don't log any deprecations. + config.active_support.report_deprecations = false + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false + + # Enable DNS rebinding protection and other `Host` header attacks. + # config.hosts = [ + # "example.com", # Allow requests from example.com + # /.*\.example\.com/ # Allow requests from subdomains like `www.example.com` + # ] + # Skip DNS rebinding protection for the default health check endpoint. + # config.host_authorization = { exclude: ->(request) { request.path == "/up" } } +end diff --git a/config/environments/test.rb b/config/environments/test.rb new file mode 100644 index 0000000..adbb4a6 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,64 @@ +require "active_support/core_ext/integer/time" + +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # While tests run files are not watched, reloading is not necessary. + config.enable_reloading = false + + # Eager loading loads your entire application. When running a single test locally, + # this is usually not necessary, and can slow down your test suite. However, it's + # recommended that you enable it in continuous integration systems to ensure eager + # loading is working properly before deploying your code. + config.eager_load = ENV["CI"].present? + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + "Cache-Control" => "public, max-age=#{1.hour.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + config.cache_store = :null_store + + # Render exception templates for rescuable exceptions and raise for other exceptions. + config.action_dispatch.show_exceptions = :rescuable + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory. + config.active_storage.service = :test + + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true + + # Raise error when a before_action's only/except options reference missing actions + config.action_controller.raise_on_missing_callback_actions = true +end diff --git a/config/importmap.rb b/config/importmap.rb new file mode 100644 index 0000000..bc060ed --- /dev/null +++ b/config/importmap.rb @@ -0,0 +1,7 @@ +# Pin npm packages by running ./bin/importmap + +pin "application" +pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true +pin "@hotwired/stimulus", to: "stimulus.min.js" +pin "@hotwired/stimulus-loading", to: "stimulus-loading.js" +pin_all_from "app/javascript/controllers", under: "controllers" diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 0000000..4873244 --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = "1.0" + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 0000000..b3076b3 --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy. +# See the Securing Rails Applications Guide for more information: +# https://guides.rubyonrails.org/security.html#content-security-policy-header + +# Rails.application.configure do +# config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end +# +# # Generate session nonces for permitted importmap, inline scripts, and inline styles. +# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } +# config.content_security_policy_nonce_directives = %w(script-src style-src) +# +# # Report violations without enforcing the policy. +# # config.content_security_policy_report_only = true +# end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000..c2d89e2 --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file. +# Use this to limit dissemination of sensitive information. +# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. +Rails.application.config.filter_parameters += [ + :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn +] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb new file mode 100644 index 0000000..3860f65 --- /dev/null +++ b/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, "\\1en" +# inflect.singular /^(ox)en/i, "\\1" +# inflect.irregular "person", "people" +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym "RESTful" +# end diff --git a/config/initializers/permissions_policy.rb b/config/initializers/permissions_policy.rb new file mode 100644 index 0000000..7db3b95 --- /dev/null +++ b/config/initializers/permissions_policy.rb @@ -0,0 +1,13 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide HTTP permissions policy. For further +# information see: https://developers.google.com/web/updates/2018/06/feature-policy + +# Rails.application.config.permissions_policy do |policy| +# policy.camera :none +# policy.gyroscope :none +# policy.microphone :none +# policy.usb :none +# policy.fullscreen :self +# policy.payment :self, "https://secure.example.com" +# end diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000..6c349ae --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,31 @@ +# Files in the config/locales directory are used for internationalization and +# are automatically loaded by Rails. If you want to use locales other than +# English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t "hello" +# +# In views, this is aliased to just `t`: +# +# <%= t("hello") %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# To learn more about the API, please read the Rails Internationalization guide +# at https://guides.rubyonrails.org/i18n.html. +# +# Be aware that YAML interprets the following case-insensitive strings as +# booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings +# must be quoted to be interpreted as strings. For example: +# +# en: +# "yes": yup +# enabled: "ON" + +en: + hello: "Hello world" diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 0000000..afa809b --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,35 @@ +# This configuration file will be evaluated by Puma. The top-level methods that +# are invoked here are part of Puma's configuration DSL. For more information +# about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. + +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } +threads min_threads_count, max_threads_count + +# Specifies that the worker count should equal the number of processors in production. +if ENV["RAILS_ENV"] == "production" + require "concurrent-ruby" + worker_count = Integer(ENV.fetch("WEB_CONCURRENCY") { Concurrent.physical_processor_count }) + workers worker_count if worker_count > 1 +end + +# Specifies the `worker_timeout` threshold that Puma will use to wait before +# terminating a worker in development environments. +worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the `pidfile` that Puma will use. +pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } + +# Allow puma to be restarted by `bin/rails restart` command. +plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000..a125ef0 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,10 @@ +Rails.application.routes.draw do + # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html + + # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. + # Can be used by load balancers and uptime monitors to verify that the app is live. + get "up" => "rails/health#show", as: :rails_health_check + + # Defines the root path route ("/") + # root "posts#index" +end diff --git a/config/storage.yml b/config/storage.yml new file mode 100644 index 0000000..4942ab6 --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket-<%= Rails.env %> + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket-<%= Rails.env %> + +# Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name-<%= Rails.env %> + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000..d4a2a0c --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,14 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema[7.1].define(version: 0) do +end diff --git a/db/seeds.rb b/db/seeds.rb new file mode 100644 index 0000000..4fbd6ed --- /dev/null +++ b/db/seeds.rb @@ -0,0 +1,9 @@ +# This file should ensure the existence of records required to run the application in every environment (production, +# development, test). The code here should be idempotent so that it can be executed at any point in every environment. +# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). +# +# Example: +# +# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name| +# MovieGenre.find_or_create_by!(name: genre_name) +# end diff --git a/dev/mythcoders.test.crt b/dev/mythcoders.test.crt new file mode 100644 index 0000000..fd297b2 --- /dev/null +++ b/dev/mythcoders.test.crt @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEczCCAtugAwIBAgIQWSln4YRh+mPRkMcO/HhZXzANBgkqhkiG9w0BAQsFADCB +kzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTQwMgYDVQQLDCtqbWFk +a2luc0BKdXN0aW5zLWlNYWMubG9jYWwgKEp1c3RpbiBBZGtpbnMpMTswOQYDVQQD +DDJta2NlcnQgam1hZGtpbnNASnVzdGlucy1pTWFjLmxvY2FsIChKdXN0aW4gQWRr +aW5zKTAeFw0yMzA4MzEwMzQ0NThaFw0yNTEyMDEwNDQ0NThaMF4xJzAlBgNVBAoT +Hm1rY2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0ZTEzMDEGA1UECwwqamFka2lu +c0BKdXN0aW5zLU1CUC5zYW1hZGEgKEp1c3RpbiBBZGtpbnMpMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnzdv+rpmGL79b+ZvGAR47HYc47/VwOe/HHP +6gzBd+CGrfeTi9T+ZU4psVXu19TsuyFFh8isGd2qdAbVbNsbDNA7YdupeV6R5d3l +EmqdCiEepdw64/Xra3RjT4ZKDYmJzqUQrZzg1Xsy1X+gFw0cuajH42wuh8OiXLCW +G2s7v838Sl8KhbhY9TTIb8gnSR9DrU83jkkNAqlWWUmVVjkNl+U9PJ+YkVdG8rZB +/nb6jM8dNyRh2xoWLla9ijYvG68U+teHM+iLl3ItgG1OzgLD7BLcGzWSWuLYE7Uo +FMJY9KEcEhtLBZEU+nC0ks1JsnOD3uToLyXR/M2/pf5WURfFUQIDAQABo3cwdTAO +BgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHwYDVR0jBBgwFoAU +GZqJlFARlW96cJzc/ywmAyuXREEwLQYDVR0RBCYwJIIPbXl0aGNvZGVycy50ZXN0 +ghEqLm15dGhjb2RlcnMudGVzdDANBgkqhkiG9w0BAQsFAAOCAYEAydwcmfDPiH7p +TJDLkjABvTKPe6IzXQxFAjaKv8wWSVvd14up/8TZURawRO+iX+M4w2/MYEHtGr97 +FawNKWIaq2jkMvp9ZH7iZ0f1eekTmH9Ct8kcO8ghh65zSlv0LLaIfu7koqmH/H0B +N4zHmJGt8Q2DrVX+JKyzZ301NCNOe3V0+LL1tscDYHKMDpgHLOoHMno8LV6MkDSD +V0oIDcNHUWOLZV7omxncnq1q5MidRv0X2a/MapYBrj/KpFIyKYU3A9FLJJD22OEB +GKRuLBhFyMoScVcrpvPACqI8ceBb9htNRmJwvDEd8yyvUSYtY4PojbbGM4R7Xt60 +k8VBBmhH2jsSwh7bqv0EUIpHgp7bWV4moXVi3HM0UjPYCWzfxoGVs3glFhinb5R4 +v+M7Z5a5U0t/G+953EfJqsopKza0oDT+nbmEmuLBF2K/ou7DzXY4/pW2V5CFGeE2 +cFyKzgIZ+wjw4zFOp/lwbNXXiufdVJFdMi7jEA2l0gtbfS1KLRsv +-----END CERTIFICATE----- diff --git a/dev/mythcoders.test.key b/dev/mythcoders.test.key new file mode 100644 index 0000000..62970ba --- /dev/null +++ b/dev/mythcoders.test.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCWfN2/6umYYvv1 +v5m8YBHjsdhzjv9XA578cc/qDMF34Iat95OL1P5lTimxVe7X1Oy7IUWHyKwZ3ap0 +BtVs2xsM0Dth26l5XpHl3eUSap0KIR6l3Drj9etrdGNPhkoNiYnOpRCtnODVezLV +f6AXDRy5qMfjbC6Hw6JcsJYbazu/zfxKXwqFuFj1NMhvyCdJH0OtTzeOSQ0CqVZZ +SZVWOQ2X5T08n5iRV0bytkH+dvqMzx03JGHbGhYuVr2KNi8brxT614cz6IuXci2A +bU7OAsPsEtwbNZJa4tgTtSgUwlj0oRwSG0sFkRT6cLSSzUmyc4Pe5OgvJdH8zb+l +/lZRF8VRAgMBAAECggEAc0xQCc7OErckHHEkNLPWgQGtuTwCXoSjtv7sMYJ8aIBa +L8fT//q8vplYUEpqqGq2xdkEELirQ1YWVrc1piVpYDPai2tlOVw/pEKSU73je/NM +K//EDwxHxxhxTmixLBYIw46sbJgZmva9R950pbSiIY0zOQeVzucQ6rtRBsjuClF2 +/vEQiXStrSZcr1cFk8RaWEXT8xkSprZzUXpqLfACWPG61olSmjChX2eUng4QxaiE +cWo6QZeMxrp4//385Y2GT7buuOviGAV86VyFwCCrN5hhZr4HGkcpbuSOXWZgHPuH +tVDh7kCtulof351xSY1kulgyrYDLjm2fVTub/R63EQKBgQDHxsmb5wvpATJl8/UD +T77PkOHhvfywYKyWBEkZxKtw+ODy9LOVv9ST+NSzutZA68Etoplk9ecUuf3Gi+p/ +RDrS9yYe9ak84eOMuFMJ6RJTP+mEdxDg47KHvRrDvcND9X+dzwfgMiGLXlqK5oIk +e6V1iUzmuda6AEYcprhbkcrb3wKBgQDA1v4yQzPQYoWL6ie/pOWc0Dcwcq/P6yIf +Thmb+NsLahMjREqCQpOBcKXsx6RSAtB/9OOEkwt9yEAWCkWVrdbHmyt4b7Vui0NZ +zDHEWb20UQZcw7Ht7ku5ZTHZKhYJlFokllwqNAbL5MUWT4l72dZn3QCJqHAv3wjm +/rpmYW+EzwKBgQCaoAUJszHnvbJpcQJR9tYkR+pdVDSRu7G5R0XhOPTNMwTBZ57c +KCb8BNt05QbSJudVUAXUO/QIedCvbToqGQBCq2KJEfFUmy4Ji91RzWEOqGgwzAt3 +VSWopDhkCqtpHUoSNdzNrV+DRJtl6PYQENfG+mdYKbzGKFIb+Pq2fUh7FwKBgD7r +Jt8xbAt2ycn/6V4vKDfE++zTzqdROb3rFpH8XUPZJUthccoUfNpD7e9WqDeV8X9+ +YGmWLK6qkrZePZv7r1NLPqC6GgFqcNwwsqA1A598vE2yEDDoik6ARQZtI+mWPN8p +LAMdHIaUKvX/l4UQa1NSGWXQzmHgLKBpxlm3OtKjAoGBAKp+YQWXpX0VtTekI9Ik +SHB8YvGp0o03hUfqBE5Rad5nHwrgj460N+dMd4/iQpJfQpVzDm8XpXX5fcLzME5+ +xeyiQiMgPMOb/pzHfLEyq5itWcXzvmiElHnTmPoKUK84Qiwcpg4JMwUANxxhzXDG +pI7yZLvMNeFaknyboXQ8KY4P +-----END PRIVATE KEY----- diff --git a/dev/nginx.conf b/dev/nginx.conf new file mode 100644 index 0000000..0ac55cb --- /dev/null +++ b/dev/nginx.conf @@ -0,0 +1,43 @@ +events { } + +http { + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + client_max_body_size 0; + + server { + listen 80; + http2 on; + server_name hermes.mythcoders.test; + return 301 https://$host$request_uri; + } + + server { + listen 443 ssl; + http2 on; + server_name hermes.mythcoders.test; + + ssl_certificate /ssl/mythcoders.test.crt; + ssl_certificate_key /ssl/mythcoders.test.key; + + access_log /var/log/nginx/access.log combined; + error_log /var/log/nginx/error.log; + + location / { + proxy_pass http://hermes-app:3000/; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_redirect http://hermes-app:3000/ $scheme://$http_host/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_read_timeout 20d; + proxy_buffering off; + } + } +} diff --git a/dev/rules.yml b/dev/rules.yml new file mode 100644 index 0000000..698b124 --- /dev/null +++ b/dev/rules.yml @@ -0,0 +1,6 @@ +tls: + stores: + default: + defaultCertificate: + certFile: /etc/traefik/mythcoders.test.crt + keyFile: /etc/traefik/mythcoders.test.key diff --git a/dev/setup.yml b/dev/setup.yml new file mode 100644 index 0000000..8561541 --- /dev/null +++ b/dev/setup.yml @@ -0,0 +1,152 @@ +--- +- hosts: localhost + gather_facts: false + connection: local + vars: + network_name: hermes + handlers: + - name: restart dnsmasq + become: yes + command: brew services restart dnsmasq + - name: setup mkcert + become: yes + command: mkcert --install + pre_tasks: + - name: install dnsmasq + homebrew: name=dnsmasq + + - name: install mkcert + homebrew: name=mkcert + + - name: install nss + homebrew: name=nss + tasks: + - name: net tier - certificate + copy: + dest: "~/Library/Application Support/mkcert/rootCA.pem" + content: | + -----BEGIN CERTIFICATE----- + MIIE9zCCA1+gAwIBAgIQH5gt+MfkJUMRNsUSBjZmhjANBgkqhkiG9w0BAQsFADCB + kzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTQwMgYDVQQLDCtqbWFk + a2luc0BKdXN0aW5zLWlNYWMubG9jYWwgKEp1c3RpbiBBZGtpbnMpMTswOQYDVQQD + DDJta2NlcnQgam1hZGtpbnNASnVzdGlucy1pTWFjLmxvY2FsIChKdXN0aW4gQWRr + aW5zKTAeFw0yMDAzMzAwNjQ2MjNaFw0zMDAzMzAwNjQ2MjNaMIGTMR4wHAYDVQQK + ExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExNDAyBgNVBAsMK2ptYWRraW5zQEp1c3Rp + bnMtaU1hYy5sb2NhbCAoSnVzdGluIEFka2lucykxOzA5BgNVBAMMMm1rY2VydCBq + bWFka2luc0BKdXN0aW5zLWlNYWMubG9jYWwgKEp1c3RpbiBBZGtpbnMpMIIBojAN + BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA3dzDC+S254Q32Hh+zbVIsWi4RDxN + ELOeypZFjRNbsRMhNo8UBxyV9IfQVHQdYzZxdvCeSDj9afRlzEEUwHHuqEEvy4Ap + P1N7qynpmorkazwaCQq1lAqnq6HK2ofXCCwTJyHDh4ggNST8Dp+YnamI7M089Fy6 + YWMSbywC7SRUc9bSeKbECB8mDCMBanyWopqecXYLUdLsPOn3tXTpiYhmYuVYxpj/ + AsAwIousmjarJ7+FxdouqwkYD/hLwdODzae8XTFeT7i/0is44dam7YKidMgFp1tc + g/XidyXnbCBIxfjacks2T7iRlCnn4xTX7ETfVaHKVcNXhHmxkP7tR8vQ/uchIiRa + /2rGJjpxIqGcOYiequ6G1dkQ81KvZSjgYdO2gaPBAITPSVCSfV7hmsXseLaVuFmO + kjPctqpi56XOjbs25WHToid3cDZXvWH9cW2WYHrJHg+0AS9ZAYzPGQD4cedJw+ld + iOXzSe/SMnSl0KQbGXmoXmkbxLGqDgF7l+FvAgMBAAGjRTBDMA4GA1UdDwEB/wQE + AwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQZmomUUBGVb3pwnNz/ + LCYDK5dEQTANBgkqhkiG9w0BAQsFAAOCAYEAMuMTWabDrwnidFWCnjWedTMuqwa3 + qxWJwkUJILD4862eDjmmXzz8SBeEJTiemhPheoApJXy/BYlBnmIdnnQoC2Wjg5KC + 2Z4ZlnXAmJr99EjpddYXr1jU0iDTx7OdVHMp53K6675iEqseoccPk1RAhcFav7fV + 3NvWBK/obB1KQWAHaf2e2OLcLqY43zpI8974GOgBRoO2z8Kgyc23Egjzp4ZTFE0U + r8Dp8NlLU8W1NtW+RQeCX8hOjNAT34bkR+25QQHAiSqsyfXMkK05/Z3H4e2KViHL + pCXtScmkueVBAURFJMUBkBZK+25b0oJLqIy2NDVTg7HnEqQGc7n/VuOIqiCX4oOe + 3OFt/pOFtJn05W4vu6SfeFsk9KNlQLNgQGm8ktBj7XUTksCtd1b8wXOzt7DefQC/ + SFhknVIs9pnnygkfq9cwvArL4n1LcTj830gt0/KEdW4CtSpzOT2KW1zXFB100h+Q + uRwm/oeyO6GCrU7t1rklKkKC7yzICO1pnhmK + -----END CERTIFICATE----- + notify: setup mkcert + + - name: net tier - private key + copy: + dest: "~/Library/Application Support/mkcert/rootCA-key.pem" + content: | + -----BEGIN PRIVATE KEY----- + MIIHAAIBADANBgkqhkiG9w0BAQEFAASCBuowggbmAgEAAoIBgQDd3MML5LbnhDfY + eH7NtUixaLhEPE0Qs57KlkWNE1uxEyE2jxQHHJX0h9BUdB1jNnF28J5IOP1p9GXM + QRTAce6oQS/LgCk/U3urKemaiuRrPBoJCrWUCqerocrah9cILBMnIcOHiCA1JPwO + n5idqYjszTz0XLphYxJvLALtJFRz1tJ4psQIHyYMIwFqfJaimp5xdgtR0uw86fe1 + dOmJiGZi5VjGmP8CwDAii6yaNqsnv4XF2i6rCRgP+EvB04PNp7xdMV5PuL/SKzjh + 1qbtgqJ0yAWnW1yD9eJ3JedsIEjF+NpySzZPuJGUKefjFNfsRN9VocpVw1eEebGQ + /u1Hy9D+5yEiJFr/asYmOnEioZw5iJ6q7obV2RDzUq9lKOBh07aBo8EAhM9JUJJ9 + XuGaxex4tpW4WY6SM9y2qmLnpc6NuzblYdOiJ3dwNle9Yf1xbZZgeskeD7QBL1kB + jM8ZAPhx50nD6V2I5fNJ79IydKXQpBsZeaheaRvEsaoOAXuX4W8CAwEAAQKCAYEA + opQ41glXQxavudCq02GKEH91sIMj0h5eOYSfGP9bjMpA53M3sPJwrM2ti4W/V0m5 + Ifi3dKNWiINQ6bmzVEbpJaEHPi//ielKUaaYCejH9BEJ3yBa6U5Zijs4pKUwnUt3 + CZEDcNj/CRK+JpUrSDXJIgZQKZ2d8umfw5nT1yVtQanleAZ01qLExdYNHpSH6kY1 + 310qdF6FQSoOnIk87czngocgZAAPt1tQqrAB3sw65hjCFbeJxUoXuPQxx6qRBm5o + C8qLpgHb2I/jkrZNlZ7hYVn5E+T4PXPzkOFtDYLPh3VpHeldX6ODRD8E44zaw6/9 + ZZ7+SeHDYhoKAJl3MvdxU27a/GihMjp37g3N9//KxfhljHMzrWGdmuIRQkA1kFVD + vbUhXNVM7x/y0sCyz8t852eTlUZqrkjwknEuKSIQPAK5d4m0DiFPxoAAtgPWjab+ + +hcc/sCD7zOPc/KoVWW3LgqnjZFzzCtEf0cD4wqOK5wWKDDjrGdIei46EIK0zh9x + AoHBAOcDmV2+eCAmqCPw96jA+ABWILDfPpDLvojaovFMKa/yBd12K2dsBEzi7UA/ + hLQgSCa982k57m0B4CA9PSkcABMV4xTKCWjklBMAKG2/UOdwQTe8miJLQ5x1LKbD + g2jtWqfT51MPN7gf6On9cpYrsmge8ol/ypudgN3Aq+CHWYQO94b7igLcRIuT39rV + lT+CPn21xjrasrR7dJK71FPFno892RKPy5eW56n2QvwjE7ytHtc0QPBcKWo4FehE + kpFcFwKBwQD128RbHWdk2qaHp3RCfREgH8/rIsVTvL8ex+K3vHxLcykFYQbfRmai + F6oPyTJGCSHloUx2op4HuCWQW+WPzZirH+9nWcQ01TcGP8pUrel8IulUdzdBu/sV + YDRd6muR3HAv4pY68H/84kr3GhTGO7vPpyZAZL0ZXE9Nb1aQexxn/e+O6XxEzN13 + czTaZSZWs9qrqsjT6+97J+cvofUM6rqLsdlBe5fUXmum6Dv27j1pcFurRa017OUK + YSnXbY11RGkCgcEAzEYbdJB7KnrkTTvD0x4nbiy6pYwSh/kR13P1h4dAiYtqckUO + 5lnWh6JWBmzkTF8LTe7DcXW/hfaVmAxuq45N5pKBBR4OKgmNgiuulDULNkvF76I/ + bTm+ZHgcbq4N4leXxTWUpJadP5w/2cC6dV3YWUecUceFggtJK0027sjgd+zAJkUA + 6byahA3TcW9RlSH3XjPBQMOoJ/3Ou/2JKDZkGeenrkkmzzmqSlkvLENcLYer8MIM + 9j2YhYtom8UfEZgrAoHBAK6ttQXTj1ltrDHnfMecmmVLlOsIKlEDYnrZI7DNfzYQ + HQ4QUNSj7VmvHInYthpidK30+yGzCjqL0EyPrjuMpLK4nty8P5YWAuEyw2uEoMYs + +8CibyUKDSuzzaEIY+MfTqoHABviMd0XXpHP+wCZAihYJupLaLszBbkLqOJARf9w + wRq1szAiqhsrRFsC0Ml7QZsEXWmMUPscb7o9BKFnyKBl/Oj0ifw+FZhhmfEodYOL + a+X1PEp7BIRqYlMIKCAwOQKBwQDLV6YUAXOo+Sh9M8J2jTeoErKg7yRoh8aDv9jh + EjsUjaVC5EYhf7a1VQRemDvb+3uI9Bone6+vJHZsnbDoZ2MZ3kU9OOFxTvsoWNWw + M1C/X5nooPQieW2gnKKOZbcx3KnMkD8N5Kxn+vvsUIR9aboj0gsWBprjmkqVtsbL + kQ3pjh5Z1Qm5HzWtwlsCPHOIqB1asjBfiE88yPE89jdglDnz3tNeZTgRq29hB2/F + KP3tqmSdf2gxW2lX2BSDaFAFcW0= + -----END PRIVATE KEY----- + notify: setup mkcert + + - name: net tier - network resovler + become: yes + lineinfile: + state: present + line: nameserver 127.0.0.1 + create: yes + dest: /etc/resolver/mythcoders.test + + - name: net tier - configure dns + become: yes + lineinfile: + state: present + line: address=/mythcoders.test/127.0.0.1 + create: yes + dest: /usr/local/etc/dnsmasq.conf + notify: restart dnsmasq + + - name: net tier - configure dns + become: yes + lineinfile: + state: present + line: no-resolv + create: yes + dest: /usr/local/etc/dnsmasq.conf + notify: restart dnsmasq + + - name: net tier - configure dns + become: yes + lineinfile: + state: present + line: bogus-priv + create: yes + dest: /usr/local/etc/dnsmasq.conf + notify: restart dnsmasq + + - name: net tier - configure dns + become: yes + lineinfile: + state: present + line: domain-needed + create: yes + dest: /usr/local/etc/dnsmasq.conf + notify: restart dnsmasq + + - name: inf tier - docker network + docker_network: + name: "{{ network_name }}" + internal: no diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..426fd59 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,59 @@ +version: "3.7" + +x-shared-environment-variables: &shared-environment-variables + RAILS_ENV: development + NODE_ENV: development + +services: + app: + image: hermes + build: + context: . + target: build + container_name: hermes-app + command: ["./bin/rails", "server", "-b", "0.0.0.0"] + volumes: + - .:/rails + environment: + <<: *shared-environment-variables + stdin_open: true + tty: true + + # worker: + # image: hermes + # container_name: hermes-worker + # command: ["bundle", "exec", "rake", "solid_queue:start"] + # volumes: + # - .:/rails + # environment: + # <<: *shared-environment-variables + + css: + image: hermes + container_name: hermes-css + command: ["sh", "./scripts/css"] + volumes: + - .:/rails + environment: + <<: *shared-environment-variables + stdin_open: true + tty: true + depends_on: + - app + + web: + image: nginx:latest + container_name: hermes-web + volumes: + - ./dev/nginx.conf:/etc/nginx/nginx.conf + - ./dev/mythcoders.test.crt:/ssl/mythcoders.test.crt + - ./dev/mythcoders.test.key:/ssl/mythcoders.test.key + - ./log:/var/log/nginx + ports: + - "80:80" + - "443:443" + +networks: + default: + name: hermes_dev + external: true diff --git a/lib/assets/.keep b/lib/assets/.keep new file mode 100644 index 0000000..e69de29 diff --git a/lib/email_helper.rb b/lib/email_helper.rb new file mode 100644 index 0000000..acc832d --- /dev/null +++ b/lib/email_helper.rb @@ -0,0 +1,15 @@ +module EmailHelper + def self.delivering_email(message) + message.to = ["justin@mythcoders.com"] + message.subject = "[REROUTED] #{message.subject}" + end + + def self.delivered_email(message) + recipients = Array(message.to) + Array(message.bcc) + Array(message.cc) + + EmailLog.create!( + subject: message.subject, + recipients: recipients.join(", ") + ) + end +end diff --git a/lib/tasks/.keep b/lib/tasks/.keep new file mode 100644 index 0000000..e69de29 diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake new file mode 100644 index 0000000..60381ab --- /dev/null +++ b/lib/tasks/auto_annotate_models.rake @@ -0,0 +1,59 @@ +# NOTE: only doing this in development as some production environments (Heroku) +# NOTE: are sensitive to local FS writes, and besides -- it's just not proper +# NOTE: to have a dev-mode tool do its thing in production. +if Rails.env.development? + require "annotate" + task :set_annotation_options do + # You can override any of these by setting an environment variable of the + # same name. + Annotate.set_defaults( + "active_admin" => "false", + "additional_file_patterns" => [], + "routes" => "false", + "models" => "true", + "position_in_routes" => "before", + "position_in_class" => "before", + "position_in_test" => "before", + "position_in_fixture" => "before", + "position_in_factory" => "before", + "position_in_serializer" => "before", + "show_foreign_keys" => "true", + "show_complete_foreign_keys" => "false", + "show_indexes" => "true", + "simple_indexes" => "false", + "model_dir" => "app/models", + "root_dir" => "", + "include_version" => "false", + "require" => "", + "exclude_tests" => "false", + "exclude_fixtures" => "false", + "exclude_factories" => "false", + "exclude_serializers" => "false", + "exclude_scaffolds" => "true", + "exclude_controllers" => "true", + "exclude_helpers" => "true", + "exclude_sti_subclasses" => "false", + "ignore_model_sub_dir" => "false", + "ignore_columns" => nil, + "ignore_routes" => nil, + "ignore_unknown_models" => "false", + "hide_limit_column_types" => "integer,bigint,boolean", + "hide_default_column_types" => "json,jsonb,hstore", + "skip_on_db_migrate" => "false", + "format_bare" => "true", + "format_rdoc" => "false", + "format_yard" => "false", + "format_markdown" => "false", + "sort" => "false", + "force" => "false", + "frozen" => "false", + "classified_sort" => "true", + "trace" => "false", + "wrapper_open" => nil, + "wrapper_close" => nil, + "with_comment" => "true" + ) + end + + Annotate.load_tasks +end diff --git a/log/.keep b/log/.keep new file mode 100644 index 0000000..e69de29 diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000..2be3af2 --- /dev/null +++ b/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/422.html b/public/422.html new file mode 100644 index 0000000..c08eac0 --- /dev/null +++ b/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/500.html b/public/500.html new file mode 100644 index 0000000..78a030a --- /dev/null +++ b/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/apple-touch-icon-precomposed.png b/public/apple-touch-icon-precomposed.png new file mode 100644 index 0000000..e69de29 diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..e69de29 diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..c19f78a --- /dev/null +++ b/public/robots.txt @@ -0,0 +1 @@ +# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/storage/.keep b/storage/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb new file mode 100644 index 0000000..d19212a --- /dev/null +++ b/test/application_system_test_case.rb @@ -0,0 +1,5 @@ +require "test_helper" + +class ApplicationSystemTestCase < ActionDispatch::SystemTestCase + driven_by :selenium, using: :chrome, screen_size: [1400, 1400] +end diff --git a/test/channels/application_cable/connection_test.rb b/test/channels/application_cable/connection_test.rb new file mode 100644 index 0000000..6340bf9 --- /dev/null +++ b/test/channels/application_cable/connection_test.rb @@ -0,0 +1,13 @@ +require "test_helper" + +module ApplicationCable + class ConnectionTest < ActionCable::Connection::TestCase + # test "connects with cookies" do + # cookies.signed[:user_id] = 42 + # + # connect + # + # assert_equal connection.user_id, "42" + # end + end +end diff --git a/test/controllers/.keep b/test/controllers/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/helpers/.keep b/test/helpers/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/integration/.keep b/test/integration/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/mailers/.keep b/test/mailers/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/models/.keep b/test/models/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/system/.keep b/test/system/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000..0c22470 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,15 @@ +ENV["RAILS_ENV"] ||= "test" +require_relative "../config/environment" +require "rails/test_help" + +module ActiveSupport + class TestCase + # Run tests in parallel with specified workers + parallelize(workers: :number_of_processors) + + # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. + fixtures :all + + # Add more helper methods to be used by all tests here... + end +end diff --git a/tmp/.keep b/tmp/.keep new file mode 100644 index 0000000..e69de29 diff --git a/tmp/pids/.keep b/tmp/pids/.keep new file mode 100644 index 0000000..e69de29 diff --git a/tmp/storage/.keep b/tmp/storage/.keep new file mode 100644 index 0000000..e69de29 diff --git a/vendor/.keep b/vendor/.keep new file mode 100644 index 0000000..e69de29 diff --git a/vendor/javascript/.keep b/vendor/javascript/.keep new file mode 100644 index 0000000..e69de29 From 2ad6a9a9b1adad73d55d98a876f763134d9546e6 Mon Sep 17 00:00:00 2001 From: Justin Adkins Date: Mon, 15 Jan 2024 02:15:17 -0500 Subject: [PATCH 03/24] WIP --- Gemfile | 4 +- app/models/blacklisted_email.rb | 12 ++ app/models/client.rb | 20 ++ app/models/environment.rb | 25 +++ app/models/message.rb | 28 +++ app/models/recipient.rb | 23 ++ config/application.rb | 2 +- config/environments/development.rb | 1 - config/environments/production.rb | 4 +- config/routes.rb | 2 +- db/migrate/20240115065325_create_clients.rb | 22 ++ db/migrate/20240115065341_create_messages.rb | 63 ++++++ ...1_create_solid_queue_tables.solid_queue.rb | 101 +++++++++ db/schema.rb | 199 +++++++++++++++++- 14 files changed, 498 insertions(+), 8 deletions(-) create mode 100644 app/models/blacklisted_email.rb create mode 100644 app/models/client.rb create mode 100644 app/models/environment.rb create mode 100644 app/models/message.rb create mode 100644 app/models/recipient.rb create mode 100644 db/migrate/20240115065325_create_clients.rb create mode 100644 db/migrate/20240115065341_create_messages.rb create mode 100644 db/migrate/20240115071411_create_solid_queue_tables.solid_queue.rb diff --git a/Gemfile b/Gemfile index 5bf31f7..2740ca1 100644 --- a/Gemfile +++ b/Gemfile @@ -13,7 +13,7 @@ gem "solid_queue" gem "sqlite3", "~> 1.4" gem "stimulus-rails" gem "turbo-rails" -gem "tzinfo-data", platforms: %i[ windows jruby ] +gem "tzinfo-data", platforms: %i[windows jruby] gem "view_component" # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] @@ -21,7 +21,7 @@ gem "view_component" group :development, :test do gem "annotate" - gem "debug", platforms: %i[ mri windows ] + gem "debug", platforms: %i[mri windows] gem "dotenv-rails" gem "standard" end diff --git a/app/models/blacklisted_email.rb b/app/models/blacklisted_email.rb new file mode 100644 index 0000000..4cfd3e4 --- /dev/null +++ b/app/models/blacklisted_email.rb @@ -0,0 +1,12 @@ +# == Schema Information +# +# Table name: blacklisted_emails +# +# id :integer not null, primary key +# address :string not null +# reason :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +class BlacklistedEmail < ApplicationRecord +end diff --git a/app/models/client.rb b/app/models/client.rb new file mode 100644 index 0000000..211288a --- /dev/null +++ b/app/models/client.rb @@ -0,0 +1,20 @@ +# == Schema Information +# +# Table name: clients +# +# id :integer not null, primary key +# name :string not null +# password :string not null +# state :integer default(0), not null +# username :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_clients_on_name (name) UNIQUE +# index_clients_on_password (password) +# index_clients_on_username (username) +# +class Client < ApplicationRecord +end diff --git a/app/models/environment.rb b/app/models/environment.rb new file mode 100644 index 0000000..f9d6e21 --- /dev/null +++ b/app/models/environment.rb @@ -0,0 +1,25 @@ +# == Schema Information +# +# Table name: environments +# +# id :integer not null, primary key +# name :string not null +# regex :boolean default(FALSE), not null +# reoute_address :string +# reply_to_address :string +# status :integer not null +# created_at :datetime not null +# updated_at :datetime not null +# client_id :integer not null +# +# Indexes +# +# index_environments_on_client_id (client_id) +# index_environments_on_client_id_and_name (client_id,name) UNIQUE +# +# Foreign Keys +# +# client_id (client_id => clients.id) +# +class Environment < ApplicationRecord +end diff --git a/app/models/message.rb b/app/models/message.rb new file mode 100644 index 0000000..b2dd7dc --- /dev/null +++ b/app/models/message.rb @@ -0,0 +1,28 @@ +# == Schema Information +# +# Table name: messages +# +# id :integer not null, primary key +# content_type :string +# environment :string +# html_body :string +# priority :string +# sender :string +# sent_at :datetime +# subject :string not null +# text_body :string +# created_at :datetime not null +# updated_at :datetime not null +# client_id :integer not null +# tracking_id :string +# +# Indexes +# +# index_messages_on_client_id (client_id) +# +# Foreign Keys +# +# client_id (client_id => clients.id) +# +class Message < ApplicationRecord +end diff --git a/app/models/recipient.rb b/app/models/recipient.rb new file mode 100644 index 0000000..ed612e2 --- /dev/null +++ b/app/models/recipient.rb @@ -0,0 +1,23 @@ +# == Schema Information +# +# Table name: recipients +# +# id :integer not null, primary key +# delivered_at :datetime +# email_address :string not null +# recipient_type :string +# send_at :datetime +# created_at :datetime not null +# updated_at :datetime not null +# message_id :integer not null +# +# Indexes +# +# index_recipients_on_message_id (message_id) +# +# Foreign Keys +# +# message_id (message_id => messages.id) +# +class Recipient < ApplicationRecord +end diff --git a/config/application.rb b/config/application.rb index 71a170c..219e618 100644 --- a/config/application.rb +++ b/config/application.rb @@ -26,7 +26,7 @@ class Application < Rails::Application # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. # Common ones are `templates`, `generators`, or `middleware`, for example. - config.autoload_lib(ignore: %w(assets tasks)) + config.autoload_lib(ignore: %w[assets tasks]) # Configuration for the application, engines, and railties goes here. # diff --git a/config/environments/development.rb b/config/environments/development.rb index 37a383a..435f38c 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -60,7 +60,6 @@ # Highlight code that enqueued background job in logs. config.active_job.verbose_enqueue_logs = true - # Raises error for missing translations. # config.i18n.raise_on_missing_translations = true diff --git a/config/environments/production.rb b/config/environments/production.rb index 077936a..a1744ef 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -47,11 +47,11 @@ # Log to STDOUT by default config.logger = ActiveSupport::Logger.new(STDOUT) - .tap { |logger| logger.formatter = ::Logger::Formatter.new } + .tap { |logger| logger.formatter = ::Logger::Formatter.new } .then { |logger| ActiveSupport::TaggedLogging.new(logger) } # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # Info include generic and useful information about system operation, but avoids logging too much # information to avoid inadvertent exposure of personally identifiable information (PII). If you diff --git a/config/routes.rb b/config/routes.rb index a125ef0..9f768e5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,7 +3,7 @@ # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. # Can be used by load balancers and uptime monitors to verify that the app is live. - get "up" => "rails/health#show", as: :rails_health_check + get "up" => "rails/health#show", :as => :rails_health_check # Defines the root path route ("/") # root "posts#index" diff --git a/db/migrate/20240115065325_create_clients.rb b/db/migrate/20240115065325_create_clients.rb new file mode 100644 index 0000000..57d65ae --- /dev/null +++ b/db/migrate/20240115065325_create_clients.rb @@ -0,0 +1,22 @@ +class CreateClients < ActiveRecord::Migration[7.1] + def change + create_table :clients do |t| + t.string :name, null: false, index: {unique: true} + t.integer :state, null: false, default: 0 + t.string :username, null: false, index: true + t.string :password, null: false, index: true + t.timestamps + end + + create_table :environments do |t| + t.references :client, null: false, foreign_key: true + t.string :name, null: false + t.integer :status, null: false + t.boolean :regex, default: false, null: false + t.string :reoute_address + t.string :reply_to_address + t.index [:client_id, :name], unique: true + t.timestamps + end + end +end diff --git a/db/migrate/20240115065341_create_messages.rb b/db/migrate/20240115065341_create_messages.rb new file mode 100644 index 0000000..79575f2 --- /dev/null +++ b/db/migrate/20240115065341_create_messages.rb @@ -0,0 +1,63 @@ +class CreateMessages < ActiveRecord::Migration[7.1] + def change + create_table :callbacks do |t| + t.string :data, null: false + t.string :status, null: false + t.timestamps + end + + create_table :messages do |t| + t.references :client, null: false, foreign_key: true + t.string :tracking_id + t.string :sender + t.string :subject, null: false + t.string :html_body + t.string :content_type + t.string :priority + t.string :environment + t.string :text_body + t.datetime :sent_at + t.timestamps + end + + create_table :recipients do |t| + t.references :message, null: false, foreign_key: true + t.string :recipient_type + t.string :email_address, null: false + t.datetime :send_at + t.datetime :delivered_at + t.timestamps + end + + create_table :message_activities do |t| + t.references :message, null: false, foreign_key: true, index: true + t.references :recipient, null: true, foreign_key: true, index: true + t.string :activity_type + t.string :activity_details + t.string :ip_address + t.string :user_agent + t.string :link_url + t.string :reject_reason + t.string :reporting_mta + t.string :smtp_response + t.string :bounce_type + t.string :feedback_id + t.string :complaint_type + t.datetime :complaint_arrival_date + t.datetime :notification_timestamp + t.string :bounce_subtype + t.string :delay_type + t.datetime :expiration_time + t.string :action + t.string :status + t.string :diagnostic_code + t.timestamps + end + + create_table :blacklisted_emails do |t| + t.string :address, null: false + t.string :reason, null: false + t.timestamps + end + end +end diff --git a/db/migrate/20240115071411_create_solid_queue_tables.solid_queue.rb b/db/migrate/20240115071411_create_solid_queue_tables.solid_queue.rb new file mode 100644 index 0000000..2591b73 --- /dev/null +++ b/db/migrate/20240115071411_create_solid_queue_tables.solid_queue.rb @@ -0,0 +1,101 @@ +# This migration comes from solid_queue (originally 20231211200639) +class CreateSolidQueueTables < ActiveRecord::Migration[7.0] + def change + create_table :solid_queue_jobs do |t| + t.string :queue_name, null: false + t.string :class_name, null: false, index: true + t.text :arguments + t.integer :priority, default: 0, null: false + t.string :active_job_id, index: true + t.datetime :scheduled_at + t.datetime :finished_at, index: true + t.string :concurrency_key + + t.timestamps + + t.index [:queue_name, :finished_at], name: "index_solid_queue_jobs_for_filtering" + t.index [:scheduled_at, :finished_at], name: "index_solid_queue_jobs_for_alerting" + end + + create_table :solid_queue_scheduled_executions do |t| + t.references :job, index: {unique: true}, null: false + t.string :queue_name, null: false + t.integer :priority, default: 0, null: false + t.datetime :scheduled_at, null: false + + t.datetime :created_at, null: false + + t.index [:scheduled_at, :priority, :job_id], name: "index_solid_queue_dispatch_all" + end + + create_table :solid_queue_ready_executions do |t| + t.references :job, index: {unique: true}, null: false + t.string :queue_name, null: false + t.integer :priority, default: 0, null: false + + t.datetime :created_at, null: false + + t.index [:priority, :job_id], name: "index_solid_queue_poll_all" + t.index [:queue_name, :priority, :job_id], name: "index_solid_queue_poll_by_queue" + end + + create_table :solid_queue_claimed_executions do |t| + t.references :job, index: {unique: true}, null: false + t.bigint :process_id + t.datetime :created_at, null: false + + t.index [:process_id, :job_id] + end + + create_table :solid_queue_blocked_executions do |t| + t.references :job, index: {unique: true}, null: false + t.string :queue_name, null: false + t.integer :priority, default: 0, null: false + t.string :concurrency_key, null: false + t.datetime :expires_at, null: false + + t.datetime :created_at, null: false + + t.index [:expires_at, :concurrency_key], name: "index_solid_queue_blocked_executions_for_maintenance" + end + + create_table :solid_queue_failed_executions do |t| + t.references :job, index: {unique: true}, null: false + t.text :error + t.datetime :created_at, null: false + end + + create_table :solid_queue_pauses do |t| + t.string :queue_name, null: false, index: {unique: true} + t.datetime :created_at, null: false + end + + create_table :solid_queue_processes do |t| + t.string :kind, null: false + t.datetime :last_heartbeat_at, null: false, index: true + t.bigint :supervisor_id, index: true + + t.integer :pid, null: false + t.string :hostname + t.text :metadata + + t.datetime :created_at, null: false + end + + create_table :solid_queue_semaphores do |t| + t.string :key, null: false, index: {unique: true} + t.integer :value, default: 1, null: false + t.datetime :expires_at, null: false, index: true + + t.timestamps + + t.index [:key, :value], name: "index_solid_queue_semaphores_on_key_and_value" + end + + add_foreign_key :solid_queue_blocked_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + add_foreign_key :solid_queue_claimed_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + add_foreign_key :solid_queue_failed_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + add_foreign_key :solid_queue_ready_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + add_foreign_key :solid_queue_scheduled_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + end +end diff --git a/db/schema.rb b/db/schema.rb index d4a2a0c..9087815 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,5 +10,202 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 0) do +ActiveRecord::Schema[7.1].define(version: 2024_01_15_071411) do + create_table "blacklisted_emails", force: :cascade do |t| + t.string "address", null: false + t.string "reason", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "callbacks", force: :cascade do |t| + t.string "data", null: false + t.string "status", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "clients", force: :cascade do |t| + t.string "name", null: false + t.integer "state", default: 0, null: false + t.string "username", null: false + t.string "password", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["name"], name: "index_clients_on_name", unique: true + t.index ["password"], name: "index_clients_on_password" + t.index ["username"], name: "index_clients_on_username" + end + + create_table "environments", force: :cascade do |t| + t.integer "client_id", null: false + t.string "name", null: false + t.integer "status", null: false + t.boolean "regex", default: false, null: false + t.string "reoute_address" + t.string "reply_to_address" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["client_id", "name"], name: "index_environments_on_client_id_and_name", unique: true + t.index ["client_id"], name: "index_environments_on_client_id" + end + + create_table "message_activities", force: :cascade do |t| + t.integer "message_id", null: false + t.integer "recipient_id" + t.string "activity_type" + t.string "activity_details" + t.string "ip_address" + t.string "user_agent" + t.string "link_url" + t.string "reject_reason" + t.string "reporting_mta" + t.string "smtp_response" + t.string "bounce_type" + t.string "feedback_id" + t.string "complaint_type" + t.datetime "complaint_arrival_date" + t.datetime "notification_timestamp" + t.string "bounce_subtype" + t.string "delay_type" + t.datetime "expiration_time" + t.string "action" + t.string "status" + t.string "diagnostic_code" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["message_id"], name: "index_message_activities_on_message_id" + t.index ["recipient_id"], name: "index_message_activities_on_recipient_id" + end + + create_table "messages", force: :cascade do |t| + t.integer "client_id", null: false + t.string "tracking_id" + t.string "sender" + t.string "subject", null: false + t.string "html_body" + t.string "content_type" + t.string "priority" + t.string "environment" + t.string "text_body" + t.datetime "sent_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["client_id"], name: "index_messages_on_client_id" + end + + create_table "recipients", force: :cascade do |t| + t.integer "message_id", null: false + t.string "recipient_type" + t.string "email_address", null: false + t.datetime "send_at" + t.datetime "delivered_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["message_id"], name: "index_recipients_on_message_id" + end + + create_table "solid_queue_blocked_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.string "concurrency_key", null: false + t.datetime "expires_at", null: false + t.datetime "created_at", null: false + t.index ["expires_at", "concurrency_key"], name: "index_solid_queue_blocked_executions_for_maintenance" + t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true + end + + create_table "solid_queue_claimed_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.bigint "process_id" + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true + t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id" + end + + create_table "solid_queue_failed_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.text "error" + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true + end + + create_table "solid_queue_jobs", force: :cascade do |t| + t.string "queue_name", null: false + t.string "class_name", null: false + t.text "arguments" + t.integer "priority", default: 0, null: false + t.string "active_job_id" + t.datetime "scheduled_at" + t.datetime "finished_at" + t.string "concurrency_key" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["active_job_id"], name: "index_solid_queue_jobs_on_active_job_id" + t.index ["class_name"], name: "index_solid_queue_jobs_on_class_name" + t.index ["finished_at"], name: "index_solid_queue_jobs_on_finished_at" + t.index ["queue_name", "finished_at"], name: "index_solid_queue_jobs_for_filtering" + t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting" + end + + create_table "solid_queue_pauses", force: :cascade do |t| + t.string "queue_name", null: false + t.datetime "created_at", null: false + t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true + end + + create_table "solid_queue_processes", force: :cascade do |t| + t.string "kind", null: false + t.datetime "last_heartbeat_at", null: false + t.bigint "supervisor_id" + t.integer "pid", null: false + t.string "hostname" + t.text "metadata" + t.datetime "created_at", null: false + t.index ["last_heartbeat_at"], name: "index_solid_queue_processes_on_last_heartbeat_at" + t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id" + end + + create_table "solid_queue_ready_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_ready_executions_on_job_id", unique: true + t.index ["priority", "job_id"], name: "index_solid_queue_poll_all" + t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue" + end + + create_table "solid_queue_scheduled_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.datetime "scheduled_at", null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true + t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all" + end + + create_table "solid_queue_semaphores", force: :cascade do |t| + t.string "key", null: false + t.integer "value", default: 1, null: false + t.datetime "expires_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["expires_at"], name: "index_solid_queue_semaphores_on_expires_at" + t.index ["key", "value"], name: "index_solid_queue_semaphores_on_key_and_value" + t.index ["key"], name: "index_solid_queue_semaphores_on_key", unique: true + end + + add_foreign_key "environments", "clients" + add_foreign_key "message_activities", "messages" + add_foreign_key "message_activities", "recipients" + add_foreign_key "messages", "clients" + add_foreign_key "recipients", "messages" + add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade end From c859b0dfca8d0ec7be6cf06c2c1a0540062888aa Mon Sep 17 00:00:00 2001 From: Justin Adkins Date: Wed, 24 Jan 2024 00:11:19 -0500 Subject: [PATCH 04/24] Kamal and litestack --- .gitignore | 4 + .kamal/hooks/post-deploy.sample | 14 +++ .kamal/hooks/post-traefik-reboot.sample | 3 + .kamal/hooks/pre-build.sample | 51 ++++++++ .kamal/hooks/pre-connect.sample | 47 ++++++++ .kamal/hooks/pre-deploy.sample | 109 ++++++++++++++++++ .kamal/hooks/pre-traefik-reboot.sample | 3 + Dockerfile | 16 +-- Dockerfile.dev | 30 +++++ Gemfile | 2 +- Gemfile.lock | 23 +++- config/application.rb | 2 +- config/cable.yml | 9 +- config/database.yml | 24 +++- config/deploy.yml | 97 ++++++++++++++++ config/environments/development.rb | 3 + config/environments/production.rb | 6 +- ...1_create_solid_queue_tables.solid_queue.rb | 101 ---------------- db/schema.rb | 100 +--------------- docker-compose.yml | 32 ++--- 20 files changed, 429 insertions(+), 247 deletions(-) create mode 100755 .kamal/hooks/post-deploy.sample create mode 100755 .kamal/hooks/post-traefik-reboot.sample create mode 100755 .kamal/hooks/pre-build.sample create mode 100755 .kamal/hooks/pre-connect.sample create mode 100755 .kamal/hooks/pre-deploy.sample create mode 100755 .kamal/hooks/pre-traefik-reboot.sample create mode 100644 Dockerfile.dev create mode 100644 config/deploy.yml delete mode 100644 db/migrate/20240115071411_create_solid_queue_tables.solid_queue.rb diff --git a/.gitignore b/.gitignore index 5fb66c9..c8d0b5b 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,7 @@ # Ignore master key for decrypting credentials and more. /config/master.key + +# Ignore default Litestack SQLite databases. +/db/**/*.sqlite3 +/db/**/*.sqlite3-* diff --git a/.kamal/hooks/post-deploy.sample b/.kamal/hooks/post-deploy.sample new file mode 100755 index 0000000..75efafc --- /dev/null +++ b/.kamal/hooks/post-deploy.sample @@ -0,0 +1,14 @@ +#!/bin/sh + +# A sample post-deploy hook +# +# These environment variables are available: +# KAMAL_RECORDED_AT +# KAMAL_PERFORMER +# KAMAL_VERSION +# KAMAL_HOSTS +# KAMAL_ROLE (if set) +# KAMAL_DESTINATION (if set) +# KAMAL_RUNTIME + +echo "$KAMAL_PERFORMER deployed $KAMAL_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds" diff --git a/.kamal/hooks/post-traefik-reboot.sample b/.kamal/hooks/post-traefik-reboot.sample new file mode 100755 index 0000000..e3d9e3c --- /dev/null +++ b/.kamal/hooks/post-traefik-reboot.sample @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "Rebooted Traefik on $KAMAL_HOSTS" diff --git a/.kamal/hooks/pre-build.sample b/.kamal/hooks/pre-build.sample new file mode 100755 index 0000000..f87d811 --- /dev/null +++ b/.kamal/hooks/pre-build.sample @@ -0,0 +1,51 @@ +#!/bin/sh + +# A sample pre-build hook +# +# Checks: +# 1. We have a clean checkout +# 2. A remote is configured +# 3. The branch has been pushed to the remote +# 4. The version we are deploying matches the remote +# +# These environment variables are available: +# KAMAL_RECORDED_AT +# KAMAL_PERFORMER +# KAMAL_VERSION +# KAMAL_HOSTS +# KAMAL_ROLE (if set) +# KAMAL_DESTINATION (if set) + +if [ -n "$(git status --porcelain)" ]; then + echo "Git checkout is not clean, aborting..." >&2 + git status --porcelain >&2 + exit 1 +fi + +first_remote=$(git remote) + +if [ -z "$first_remote" ]; then + echo "No git remote set, aborting..." >&2 + exit 1 +fi + +current_branch=$(git branch --show-current) + +if [ -z "$current_branch" ]; then + echo "Not on a git branch, aborting..." >&2 + exit 1 +fi + +remote_head=$(git ls-remote $first_remote --tags $current_branch | cut -f1) + +if [ -z "$remote_head" ]; then + echo "Branch not pushed to remote, aborting..." >&2 + exit 1 +fi + +if [ "$KAMAL_VERSION" != "$remote_head" ]; then + echo "Version ($KAMAL_VERSION) does not match remote HEAD ($remote_head), aborting..." >&2 + exit 1 +fi + +exit 0 diff --git a/.kamal/hooks/pre-connect.sample b/.kamal/hooks/pre-connect.sample new file mode 100755 index 0000000..18e61d7 --- /dev/null +++ b/.kamal/hooks/pre-connect.sample @@ -0,0 +1,47 @@ +#!/usr/bin/env ruby + +# A sample pre-connect check +# +# Warms DNS before connecting to hosts in parallel +# +# These environment variables are available: +# KAMAL_RECORDED_AT +# KAMAL_PERFORMER +# KAMAL_VERSION +# KAMAL_HOSTS +# KAMAL_ROLE (if set) +# KAMAL_DESTINATION (if set) +# KAMAL_RUNTIME + +hosts = ENV["KAMAL_HOSTS"].split(",") +results = nil +max = 3 + +elapsed = Benchmark.realtime do + results = hosts.map do |host| + Thread.new do + tries = 1 + + begin + Socket.getaddrinfo(host, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) + rescue SocketError + if tries < max + puts "Retrying DNS warmup: #{host}" + tries += 1 + sleep rand + retry + else + puts "DNS warmup failed: #{host}" + host + end + end + + tries + end + end.map(&:value) +end + +retries = results.sum - hosts.size +nopes = results.count { |r| r == max } + +puts "Prewarmed %d DNS lookups in %.2f sec: %d retries, %d failures" % [ hosts.size, elapsed, retries, nopes ] diff --git a/.kamal/hooks/pre-deploy.sample b/.kamal/hooks/pre-deploy.sample new file mode 100755 index 0000000..1b280c7 --- /dev/null +++ b/.kamal/hooks/pre-deploy.sample @@ -0,0 +1,109 @@ +#!/usr/bin/env ruby + +# A sample pre-deploy hook +# +# Checks the Github status of the build, waiting for a pending build to complete for up to 720 seconds. +# +# Fails unless the combined status is "success" +# +# These environment variables are available: +# KAMAL_RECORDED_AT +# KAMAL_PERFORMER +# KAMAL_VERSION +# KAMAL_HOSTS +# KAMAL_COMMAND +# KAMAL_SUBCOMMAND +# KAMAL_ROLE (if set) +# KAMAL_DESTINATION (if set) + +# Only check the build status for production deployments +if ENV["KAMAL_COMMAND"] == "rollback" || ENV["KAMAL_DESTINATION"] != "production" + exit 0 +end + +require "bundler/inline" + +# true = install gems so this is fast on repeat invocations +gemfile(true, quiet: true) do + source "https://rubygems.org" + + gem "octokit" + gem "faraday-retry" +end + +MAX_ATTEMPTS = 72 +ATTEMPTS_GAP = 10 + +def exit_with_error(message) + $stderr.puts message + exit 1 +end + +class GithubStatusChecks + attr_reader :remote_url, :git_sha, :github_client, :combined_status + + def initialize + @remote_url = `git config --get remote.origin.url`.strip.delete_prefix("https://github.com/") + @git_sha = `git rev-parse HEAD`.strip + @github_client = Octokit::Client.new(access_token: ENV["GITHUB_TOKEN"]) + refresh! + end + + def refresh! + @combined_status = github_client.combined_status(remote_url, git_sha) + end + + def state + combined_status[:state] + end + + def first_status_url + first_status = combined_status[:statuses].find { |status| status[:state] == state } + first_status && first_status[:target_url] + end + + def complete_count + combined_status[:statuses].count { |status| status[:state] != "pending"} + end + + def total_count + combined_status[:statuses].count + end + + def current_status + if total_count > 0 + "Completed #{complete_count}/#{total_count} checks, see #{first_status_url} ..." + else + "Build not started..." + end + end +end + + +$stdout.sync = true + +puts "Checking build status..." +attempts = 0 +checks = GithubStatusChecks.new + +begin + loop do + case checks.state + when "success" + puts "Checks passed, see #{checks.first_status_url}" + exit 0 + when "failure" + exit_with_error "Checks failed, see #{checks.first_status_url}" + when "pending" + attempts += 1 + end + + exit_with_error "Checks are still pending, gave up after #{MAX_ATTEMPTS * ATTEMPTS_GAP} seconds" if attempts == MAX_ATTEMPTS + + puts checks.current_status + sleep(ATTEMPTS_GAP) + checks.refresh! + end +rescue Octokit::NotFound + exit_with_error "Build status could not be found" +end diff --git a/.kamal/hooks/pre-traefik-reboot.sample b/.kamal/hooks/pre-traefik-reboot.sample new file mode 100755 index 0000000..8cfda6d --- /dev/null +++ b/.kamal/hooks/pre-traefik-reboot.sample @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "Rebooting Traefik on $KAMAL_HOSTS..." diff --git a/Dockerfile b/Dockerfile index 498898d..2f915b5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,12 +34,7 @@ COPY . . RUN bundle exec bootsnap precompile app/ lib/ # Precompiling assets for production without requiring secret RAILS_MASTER_KEY -RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile - -# Entrypoint prepares the database. -ENTRYPOINT ["/rails/bin/docker-entrypoint"] - -EXPOSE 3000 +RUN SECRET_KEY_BASE=1 ./bin/rails assets:precompile # Final stage for app image FROM base @@ -54,9 +49,14 @@ COPY --from=build /usr/local/bundle /usr/local/bundle COPY --from=build /rails /rails # Run and own only the runtime files as a non-root user for security -RUN useradd rails --create-home --shell /bin/bash && \ +RUN groupadd --system --gid 1000 rails && \ + useradd rails --uid 1000 --gid 1000 --create-home --shell /bin/bash && \ chown -R rails:rails db log storage tmp -USER rails:rails +USER 1000:1000 + +# Entrypoint prepares the database. +ENTRYPOINT ["/rails/bin/docker-entrypoint"] # Start the server by default, this can be overwritten at runtime +EXPOSE 3000 CMD ["./bin/rails", "server"] diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000..d0ea562 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,30 @@ +# syntax = docker/dockerfile:1 + +# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile +ARG RUBY_VERSION=3.2.2 +FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base + +# Rails app lives here +WORKDIR /rails + +# Set development environment +ENV RAILS_ENV="development" \ + BUNDLE_DEPLOYMENT="1" \ + BUNDLE_PATH="/usr/local/bundle" + +# Install packages needed to build gems +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y build-essential git libvips pkg-config + +# Upgrade RubyGems and install required Bundler version +RUN gem update --system && \ + gem install bundler -v 2.4.19 + +# Install application gems +COPY Gemfile Gemfile.lock ./ +RUN bundle install + +EXPOSE 3000 + +ENTRYPOINT ["/rails/bin/docker-entrypoint"] +CMD ["./bin/rails", "server", "-b", "0.0.0.0"] diff --git a/Gemfile b/Gemfile index 2740ca1..129df59 100644 --- a/Gemfile +++ b/Gemfile @@ -8,8 +8,8 @@ gem "bcrypt" gem "bootsnap", require: false gem "importmap-rails" gem "propshaft" +gem "litestack" gem "puma", ">= 5.0" -gem "solid_queue" gem "sqlite3", "~> 1.4" gem "stimulus-rails" gem "turbo-rails" diff --git a/Gemfile.lock b/Gemfile.lock index f1a6c46..ab489ec 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -113,6 +113,13 @@ GEM erubi (1.12.0) globalid (1.2.1) activesupport (>= 6.1) + hanami-router (0.6.2) + hanami-utils (~> 0.7) + http_router (~> 0.11) + hanami-utils (0.9.2) + http_router (0.11.2) + rack (>= 1.0.0) + url_mount (~> 0.2.1) i18n (1.14.1) concurrent-ruby (~> 1.0) importmap-rails (2.0.1) @@ -126,6 +133,13 @@ GEM json (2.7.1) language_server-protocol (3.17.0.3) lint_roller (1.1.0) + litestack (0.4.2) + erubi + hanami-router + oj + rack + sqlite3 + tilt loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -157,6 +171,8 @@ GEM racc (~> 1.4) nokogiri (1.16.0-x86_64-linux) racc (~> 1.4) + oj (3.16.3) + bigdecimal (>= 3.0) parallel (1.24.0) parser (3.3.0.3) ast (~> 2.4.1) @@ -240,8 +256,6 @@ GEM rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - solid_queue (0.1.2) - rails (>= 7.0.3.1) sqlite3 (1.7.0-aarch64-linux) sqlite3 (1.7.0-arm64-darwin) sqlite3 (1.7.0-x86_64-linux) @@ -261,6 +275,7 @@ GEM railties (>= 6.0.0) stringio (3.1.0) thor (1.3.0) + tilt (2.3.0) timeout (0.4.1) turbo-rails (1.5.0) actionpack (>= 6.0.0) @@ -269,6 +284,8 @@ GEM tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) + url_mount (0.2.1) + rack view_component (3.10.0) activesupport (>= 5.2.0, < 8.0) concurrent-ruby (~> 1.0) @@ -300,11 +317,11 @@ DEPENDENCIES debug dotenv-rails importmap-rails + litestack propshaft puma (>= 5.0) rails (~> 7.1) selenium-webdriver - solid_queue sqlite3 (~> 1.4) standard stimulus-rails diff --git a/config/application.rb b/config/application.rb index 219e618..19eb594 100644 --- a/config/application.rb +++ b/config/application.rb @@ -33,7 +33,7 @@ class Application < Rails::Application # These settings can be overridden in specific environments using the files # in config/environments, which are processed later. # - # config.time_zone = "Central Time (US & Canada)" + config.time_zone = "Eastern Time (US & Canada)" # config.eager_load_paths << Rails.root.join("extras") end end diff --git a/config/cable.yml b/config/cable.yml index 3148f58..7493201 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -1,10 +1,11 @@ development: - adapter: async + adapter: litecable test: adapter: test +staging: + adapter: litecable + production: - adapter: redis - url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> - channel_prefix: hermes_production + adapter: litecable diff --git a/config/database.yml b/config/database.yml index 796466b..98790da 100644 --- a/config/database.yml +++ b/config/database.yml @@ -4,22 +4,36 @@ # Ensure the SQLite 3 gem is defined in your Gemfile # gem "sqlite3" # +# `Litesupport.root.join("data.sqlite3")` stores +# application data in the path `./db/#{Rails.env}/data.sqlite3` +# +# `Litesupport.root(env).join(path)` stores +# application data in the path `./db/#{env}/#{path}` +# +# idle_timeout should be set to zero, to avoid recycling sqlite connections +# and losing the page cache +# default: &default - adapter: sqlite3 + adapter: litedb pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> - timeout: 5000 + idle_timeout: 0 development: <<: *default - database: storage/development.sqlite3 + database: <%= Litesupport.root("development").join("data.sqlite3") %> # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default - database: storage/test.sqlite3 + database: <%= Litesupport.root("test").join("data.sqlite3") %> +# Warning: Make sure your production database path is on a persistent +# volume, otherwise your application data could be deleted between deploys. +# +# You may also set the Litesupport.root in production via the +# `LITESTACK_DATA_PATH` environment variable. production: <<: *default - database: storage/production.sqlite3 + database: <%= Litesupport.root("production").join("data.sqlite3") %> diff --git a/config/deploy.yml b/config/deploy.yml new file mode 100644 index 0000000..20bbe71 --- /dev/null +++ b/config/deploy.yml @@ -0,0 +1,97 @@ +# Name of your application. Used to uniquely configure containers. +service: my-app + +# Name of the container image. +image: user/my-app + +# Deploy to these servers. +servers: + - 192.168.0.1 + +# Credentials for your image host. +registry: + # Specify the registry server, if you're not using Docker Hub + # server: registry.digitalocean.com / ghcr.io / ... + username: my-user + + # Always use an access token rather than real password when possible. + password: + - KAMAL_REGISTRY_PASSWORD + +# Inject ENV variables into containers (secrets come from .env). +# Remember to run `kamal env push` after making changes! +# env: +# clear: +# DB_HOST: 192.168.0.2 +# secret: +# - RAILS_MASTER_KEY + +# Use a different ssh user than root +# ssh: +# user: app + +# Configure builder setup. +# builder: +# args: +# RUBY_VERSION: 3.2.0 +# secrets: +# - GITHUB_TOKEN +# remote: +# arch: amd64 +# host: ssh://app@192.168.0.1 + +# Use accessory services (secrets come from .env). +# accessories: +# db: +# image: mysql:8.0 +# host: 192.168.0.2 +# port: 3306 +# env: +# clear: +# MYSQL_ROOT_HOST: '%' +# secret: +# - MYSQL_ROOT_PASSWORD +# files: +# - config/mysql/production.cnf:/etc/mysql/my.cnf +# - db/production.sql:/docker-entrypoint-initdb.d/setup.sql +# directories: +# - data:/var/lib/mysql +# redis: +# image: redis:7.0 +# host: 192.168.0.2 +# port: 6379 +# directories: +# - data:/data + +# Configure custom arguments for Traefik +# traefik: +# args: +# accesslog: true +# accesslog.format: json + +# Configure a custom healthcheck (default is /up on port 3000) +# healthcheck: +# path: /healthz +# port: 4000 + +# Bridge fingerprinted assets, like JS and CSS, between versions to avoid +# hitting 404 on in-flight requests. Combines all files from new and old +# version inside the asset_path. +# asset_path: /rails/public/assets + +# Configure rolling deploys by setting a wait time between batches of restarts. +# boot: +# limit: 10 # Can also specify as a percentage of total hosts, such as "25%" +# wait: 2 + +# Configure the role used to determine the primary_host. This host takes +# deploy locks, runs health checks during the deploy, and follow logs, etc. +# +# Caution: there's no support for role renaming yet, so be careful to cleanup +# the previous role on the deployed hosts. +# primary_role: web + +# Controls if we abort when see a role with no hosts. Disabling this may be +# useful for more complex deploy configurations. +# +# allow_empty_roles: false diff --git a/config/environments/development.rb b/config/environments/development.rb index 435f38c..f4f02c6 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -60,6 +60,9 @@ # Highlight code that enqueued background job in logs. config.active_job.verbose_enqueue_logs = true + config.active_job.queue_adapter = :litejob + config.active_job.queue_name_prefix = "hermes_development" + # Raises error for missing translations. # config.i18n.raise_on_missing_translations = true diff --git a/config/environments/production.rb b/config/environments/production.rb index a1744ef..219aa2d 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -59,11 +59,11 @@ config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") # Use a different cache store in production. - # config.cache_store = :mem_cache_store + config.cache_store = :litecache # Use a real queuing backend for Active Job (and separate queues per environment). - # config.active_job.queue_adapter = :resque - # config.active_job.queue_name_prefix = "hermes_production" + config.active_job.queue_adapter = :litejob + config.active_job.queue_name_prefix = "hermes_production" config.action_mailer.perform_caching = false diff --git a/db/migrate/20240115071411_create_solid_queue_tables.solid_queue.rb b/db/migrate/20240115071411_create_solid_queue_tables.solid_queue.rb deleted file mode 100644 index 2591b73..0000000 --- a/db/migrate/20240115071411_create_solid_queue_tables.solid_queue.rb +++ /dev/null @@ -1,101 +0,0 @@ -# This migration comes from solid_queue (originally 20231211200639) -class CreateSolidQueueTables < ActiveRecord::Migration[7.0] - def change - create_table :solid_queue_jobs do |t| - t.string :queue_name, null: false - t.string :class_name, null: false, index: true - t.text :arguments - t.integer :priority, default: 0, null: false - t.string :active_job_id, index: true - t.datetime :scheduled_at - t.datetime :finished_at, index: true - t.string :concurrency_key - - t.timestamps - - t.index [:queue_name, :finished_at], name: "index_solid_queue_jobs_for_filtering" - t.index [:scheduled_at, :finished_at], name: "index_solid_queue_jobs_for_alerting" - end - - create_table :solid_queue_scheduled_executions do |t| - t.references :job, index: {unique: true}, null: false - t.string :queue_name, null: false - t.integer :priority, default: 0, null: false - t.datetime :scheduled_at, null: false - - t.datetime :created_at, null: false - - t.index [:scheduled_at, :priority, :job_id], name: "index_solid_queue_dispatch_all" - end - - create_table :solid_queue_ready_executions do |t| - t.references :job, index: {unique: true}, null: false - t.string :queue_name, null: false - t.integer :priority, default: 0, null: false - - t.datetime :created_at, null: false - - t.index [:priority, :job_id], name: "index_solid_queue_poll_all" - t.index [:queue_name, :priority, :job_id], name: "index_solid_queue_poll_by_queue" - end - - create_table :solid_queue_claimed_executions do |t| - t.references :job, index: {unique: true}, null: false - t.bigint :process_id - t.datetime :created_at, null: false - - t.index [:process_id, :job_id] - end - - create_table :solid_queue_blocked_executions do |t| - t.references :job, index: {unique: true}, null: false - t.string :queue_name, null: false - t.integer :priority, default: 0, null: false - t.string :concurrency_key, null: false - t.datetime :expires_at, null: false - - t.datetime :created_at, null: false - - t.index [:expires_at, :concurrency_key], name: "index_solid_queue_blocked_executions_for_maintenance" - end - - create_table :solid_queue_failed_executions do |t| - t.references :job, index: {unique: true}, null: false - t.text :error - t.datetime :created_at, null: false - end - - create_table :solid_queue_pauses do |t| - t.string :queue_name, null: false, index: {unique: true} - t.datetime :created_at, null: false - end - - create_table :solid_queue_processes do |t| - t.string :kind, null: false - t.datetime :last_heartbeat_at, null: false, index: true - t.bigint :supervisor_id, index: true - - t.integer :pid, null: false - t.string :hostname - t.text :metadata - - t.datetime :created_at, null: false - end - - create_table :solid_queue_semaphores do |t| - t.string :key, null: false, index: {unique: true} - t.integer :value, default: 1, null: false - t.datetime :expires_at, null: false, index: true - - t.timestamps - - t.index [:key, :value], name: "index_solid_queue_semaphores_on_key_and_value" - end - - add_foreign_key :solid_queue_blocked_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade - add_foreign_key :solid_queue_claimed_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade - add_foreign_key :solid_queue_failed_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade - add_foreign_key :solid_queue_ready_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade - add_foreign_key :solid_queue_scheduled_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade - end -end diff --git a/db/schema.rb b/db/schema.rb index 9087815..f038627 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_01_15_071411) do +ActiveRecord::Schema[7.1].define(version: 2024_01_15_065341) do create_table "blacklisted_emails", force: :cascade do |t| t.string "address", null: false t.string "reason", null: false @@ -105,107 +105,9 @@ t.index ["message_id"], name: "index_recipients_on_message_id" end - create_table "solid_queue_blocked_executions", force: :cascade do |t| - t.integer "job_id", null: false - t.string "queue_name", null: false - t.integer "priority", default: 0, null: false - t.string "concurrency_key", null: false - t.datetime "expires_at", null: false - t.datetime "created_at", null: false - t.index ["expires_at", "concurrency_key"], name: "index_solid_queue_blocked_executions_for_maintenance" - t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true - end - - create_table "solid_queue_claimed_executions", force: :cascade do |t| - t.integer "job_id", null: false - t.bigint "process_id" - t.datetime "created_at", null: false - t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true - t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id" - end - - create_table "solid_queue_failed_executions", force: :cascade do |t| - t.integer "job_id", null: false - t.text "error" - t.datetime "created_at", null: false - t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true - end - - create_table "solid_queue_jobs", force: :cascade do |t| - t.string "queue_name", null: false - t.string "class_name", null: false - t.text "arguments" - t.integer "priority", default: 0, null: false - t.string "active_job_id" - t.datetime "scheduled_at" - t.datetime "finished_at" - t.string "concurrency_key" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["active_job_id"], name: "index_solid_queue_jobs_on_active_job_id" - t.index ["class_name"], name: "index_solid_queue_jobs_on_class_name" - t.index ["finished_at"], name: "index_solid_queue_jobs_on_finished_at" - t.index ["queue_name", "finished_at"], name: "index_solid_queue_jobs_for_filtering" - t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting" - end - - create_table "solid_queue_pauses", force: :cascade do |t| - t.string "queue_name", null: false - t.datetime "created_at", null: false - t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true - end - - create_table "solid_queue_processes", force: :cascade do |t| - t.string "kind", null: false - t.datetime "last_heartbeat_at", null: false - t.bigint "supervisor_id" - t.integer "pid", null: false - t.string "hostname" - t.text "metadata" - t.datetime "created_at", null: false - t.index ["last_heartbeat_at"], name: "index_solid_queue_processes_on_last_heartbeat_at" - t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id" - end - - create_table "solid_queue_ready_executions", force: :cascade do |t| - t.integer "job_id", null: false - t.string "queue_name", null: false - t.integer "priority", default: 0, null: false - t.datetime "created_at", null: false - t.index ["job_id"], name: "index_solid_queue_ready_executions_on_job_id", unique: true - t.index ["priority", "job_id"], name: "index_solid_queue_poll_all" - t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue" - end - - create_table "solid_queue_scheduled_executions", force: :cascade do |t| - t.integer "job_id", null: false - t.string "queue_name", null: false - t.integer "priority", default: 0, null: false - t.datetime "scheduled_at", null: false - t.datetime "created_at", null: false - t.index ["job_id"], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true - t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all" - end - - create_table "solid_queue_semaphores", force: :cascade do |t| - t.string "key", null: false - t.integer "value", default: 1, null: false - t.datetime "expires_at", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["expires_at"], name: "index_solid_queue_semaphores_on_expires_at" - t.index ["key", "value"], name: "index_solid_queue_semaphores_on_key_and_value" - t.index ["key"], name: "index_solid_queue_semaphores_on_key", unique: true - end - add_foreign_key "environments", "clients" add_foreign_key "message_activities", "messages" add_foreign_key "message_activities", "recipients" add_foreign_key "messages", "clients" add_foreign_key "recipients", "messages" - add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade - add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade - add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade - add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade - add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade end diff --git a/docker-compose.yml b/docker-compose.yml index 426fd59..311e411 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,9 +9,11 @@ services: image: hermes build: context: . - target: build + dockerfile: ./Dockerfile.dev container_name: hermes-app command: ["./bin/rails", "server", "-b", "0.0.0.0"] + expose: + - "3000" volumes: - .:/rails environment: @@ -19,27 +21,18 @@ services: stdin_open: true tty: true - # worker: + # css: # image: hermes - # container_name: hermes-worker - # command: ["bundle", "exec", "rake", "solid_queue:start"] + # container_name: hermes-css + # command: ["sh", "./scripts/css"] # volumes: # - .:/rails # environment: # <<: *shared-environment-variables - - css: - image: hermes - container_name: hermes-css - command: ["sh", "./scripts/css"] - volumes: - - .:/rails - environment: - <<: *shared-environment-variables - stdin_open: true - tty: true - depends_on: - - app + # stdin_open: true + # tty: true + # depends_on: + # - app web: image: nginx:latest @@ -52,8 +45,3 @@ services: ports: - "80:80" - "443:443" - -networks: - default: - name: hermes_dev - external: true From b09e98bb6dd4a0131be9c05e3df2849b7d7aa58b Mon Sep 17 00:00:00 2001 From: Justin Adkins Date: Wed, 11 Sep 2024 22:03:42 -0400 Subject: [PATCH 05/24] Vanilla Rails! Rails 7.2 Ruby 3.3.4 SolidCache SolidQueue Remove docker dev env --- .ruby-version | 2 +- Dockerfile.dev | 30 --- Gemfile | 18 +- Gemfile.lock | 211 +++++++++--------- app/controllers/public_controller.rb | 2 + app/models/blacklisted_email.rb | 12 +- app/models/client.rb | 29 +-- app/models/environment.rb | 34 +-- app/models/message.rb | 28 +-- app/models/recipient.rb | 22 +- app/views/public/index.html.erb | 1 + bin/jobs | 6 + bin/setup | 5 + config/application.rb | 2 +- config/cache.yml | 17 ++ config/credentials.yml.enc | 2 +- config/database.yml | 70 +++--- config/environments/development.rb | 9 +- config/environments/production.rb | 7 +- config/environments/test.rb | 1 + .../initializers/filter_parameter_logging.rb | 2 +- config/puma.rb | 50 ++--- config/queue.yml | 18 ++ config/routes.rb | 9 +- db/cache_schema.rb | 14 ++ db/migrate/20240115065325_create_clients.rb | 10 +- db/migrate/20240115065341_create_messages.rb | 42 +--- ...6_create_solid_queue_tables.solid_queue.rb | 101 +++++++++ ...index_to_blocked_executions.solid_queue.rb | 6 + ...create_recurring_executions.solid_queue.rb | 15 ++ ...1309_create_recurring_tasks.solid_queue.rb | 21 ++ ...11310_add_name_to_processes.solid_queue.rb | 6 + ...12011311_make_name_not_null.solid_queue.rb | 17 ++ ...ng_tasks_static_to_not_null.solid_queue.rb | 6 + db/queue_schema.rb | 141 ++++++++++++ db/schema.rb | 60 ++--- dev/mythcoders.test.crt | 26 --- dev/mythcoders.test.key | 28 --- dev/nginx.conf | 43 ---- dev/rules.yml | 6 - dev/setup.yml | 152 ------------- docker-compose.yml | 47 ---- lib/tasks/auto_annotate_models.rake | 59 ----- test/fixtures/backlisted_emails.yml | 0 test/fixtures/callbacks.yml | 0 test/fixtures/clients.yml | 5 + test/fixtures/environments.yml | 0 test/fixtures/messages.yml | 0 test/fixtures/recipients.yml | 0 test/models/backlisted_email_test.rb | 7 + test/models/client_test.rb | 9 + test/models/environment_test.rb | 7 + test/models/message_test.rb | 7 + test/models/recipient_test.rb | 7 + 54 files changed, 676 insertions(+), 753 deletions(-) delete mode 100644 Dockerfile.dev create mode 100644 app/controllers/public_controller.rb create mode 100644 app/views/public/index.html.erb create mode 100755 bin/jobs create mode 100644 config/cache.yml create mode 100644 config/queue.yml create mode 100644 db/cache_schema.rb create mode 100644 db/queue_migrate/20240912011306_create_solid_queue_tables.solid_queue.rb create mode 100644 db/queue_migrate/20240912011307_add_missing_index_to_blocked_executions.solid_queue.rb create mode 100644 db/queue_migrate/20240912011308_create_recurring_executions.solid_queue.rb create mode 100644 db/queue_migrate/20240912011309_create_recurring_tasks.solid_queue.rb create mode 100644 db/queue_migrate/20240912011310_add_name_to_processes.solid_queue.rb create mode 100644 db/queue_migrate/20240912011311_make_name_not_null.solid_queue.rb create mode 100644 db/queue_migrate/20240912011312_change_solid_queue_recurring_tasks_static_to_not_null.solid_queue.rb create mode 100644 db/queue_schema.rb delete mode 100644 dev/mythcoders.test.crt delete mode 100644 dev/mythcoders.test.key delete mode 100644 dev/nginx.conf delete mode 100644 dev/rules.yml delete mode 100644 dev/setup.yml delete mode 100644 docker-compose.yml delete mode 100644 lib/tasks/auto_annotate_models.rake create mode 100644 test/fixtures/backlisted_emails.yml create mode 100644 test/fixtures/callbacks.yml create mode 100644 test/fixtures/clients.yml create mode 100644 test/fixtures/environments.yml create mode 100644 test/fixtures/messages.yml create mode 100644 test/fixtures/recipients.yml create mode 100644 test/models/backlisted_email_test.rb create mode 100644 test/models/client_test.rb create mode 100644 test/models/environment_test.rb create mode 100644 test/models/message_test.rb create mode 100644 test/models/recipient_test.rb diff --git a/.ruby-version b/.ruby-version index be94e6f..a0891f5 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.2 +3.3.4 diff --git a/Dockerfile.dev b/Dockerfile.dev deleted file mode 100644 index d0ea562..0000000 --- a/Dockerfile.dev +++ /dev/null @@ -1,30 +0,0 @@ -# syntax = docker/dockerfile:1 - -# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile -ARG RUBY_VERSION=3.2.2 -FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base - -# Rails app lives here -WORKDIR /rails - -# Set development environment -ENV RAILS_ENV="development" \ - BUNDLE_DEPLOYMENT="1" \ - BUNDLE_PATH="/usr/local/bundle" - -# Install packages needed to build gems -RUN apt-get update -qq && \ - apt-get install --no-install-recommends -y build-essential git libvips pkg-config - -# Upgrade RubyGems and install required Bundler version -RUN gem update --system && \ - gem install bundler -v 2.4.19 - -# Install application gems -COPY Gemfile Gemfile.lock ./ -RUN bundle install - -EXPOSE 3000 - -ENTRYPOINT ["/rails/bin/docker-entrypoint"] -CMD ["./bin/rails", "server", "-b", "0.0.0.0"] diff --git a/Gemfile b/Gemfile index 129df59..0387121 100644 --- a/Gemfile +++ b/Gemfile @@ -1,27 +1,29 @@ source "https://rubygems.org" -ruby "3.2.2" +ruby file: ".ruby-version" -gem "rails", "~> 7.1" +gem "rails", "~> 7.2" +gem "activerecord-enhancedsqlite3-adapter", "~> 0.8.0" gem "bcrypt" gem "bootsnap", require: false +gem "geared_pagination" gem "importmap-rails" +gem "mission_control-jobs" gem "propshaft" -gem "litestack" -gem "puma", ">= 5.0" -gem "sqlite3", "~> 1.4" +gem "puma" +gem "solid_cache" +gem "solid_queue" +gem "sqlite3" gem "stimulus-rails" gem "turbo-rails" -gem "tzinfo-data", platforms: %i[windows jruby] gem "view_component" # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] # gem "image_processing", "~> 1.2" group :development, :test do - gem "annotate" - gem "debug", platforms: %i[mri windows] + gem "debug", platforms: %i[mri mingw x64_mingw] gem "dotenv-rails" gem "standard" end diff --git a/Gemfile.lock b/Gemfile.lock index ab489ec..893d56c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,85 +1,81 @@ GEM remote: https://rubygems.org/ specs: - actioncable (7.1.2) - actionpack (= 7.1.2) - activesupport (= 7.1.2) + actioncable (7.2.1) + actionpack (= 7.2.1) + activesupport (= 7.2.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.1.2) - actionpack (= 7.1.2) - activejob (= 7.1.2) - activerecord (= 7.1.2) - activestorage (= 7.1.2) - activesupport (= 7.1.2) - mail (>= 2.7.1) - net-imap - net-pop - net-smtp - actionmailer (7.1.2) - actionpack (= 7.1.2) - actionview (= 7.1.2) - activejob (= 7.1.2) - activesupport (= 7.1.2) - mail (~> 2.5, >= 2.5.4) - net-imap - net-pop - net-smtp + actionmailbox (7.2.1) + actionpack (= 7.2.1) + activejob (= 7.2.1) + activerecord (= 7.2.1) + activestorage (= 7.2.1) + activesupport (= 7.2.1) + mail (>= 2.8.0) + actionmailer (7.2.1) + actionpack (= 7.2.1) + actionview (= 7.2.1) + activejob (= 7.2.1) + activesupport (= 7.2.1) + mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (7.1.2) - actionview (= 7.1.2) - activesupport (= 7.1.2) + actionpack (7.2.1) + actionview (= 7.2.1) + activesupport (= 7.2.1) nokogiri (>= 1.8.5) racc - rack (>= 2.2.4) + rack (>= 2.2.4, < 3.2) rack-session (>= 1.0.1) rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - actiontext (7.1.2) - actionpack (= 7.1.2) - activerecord (= 7.1.2) - activestorage (= 7.1.2) - activesupport (= 7.1.2) + useragent (~> 0.16) + actiontext (7.2.1) + actionpack (= 7.2.1) + activerecord (= 7.2.1) + activestorage (= 7.2.1) + activesupport (= 7.2.1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.2) - activesupport (= 7.1.2) + actionview (7.2.1) + activesupport (= 7.2.1) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (7.1.2) - activesupport (= 7.1.2) + activejob (7.2.1) + activesupport (= 7.2.1) globalid (>= 0.3.6) - activemodel (7.1.2) - activesupport (= 7.1.2) - activerecord (7.1.2) - activemodel (= 7.1.2) - activesupport (= 7.1.2) + activemodel (7.2.1) + activesupport (= 7.2.1) + activerecord (7.2.1) + activemodel (= 7.2.1) + activesupport (= 7.2.1) timeout (>= 0.4.0) - activestorage (7.1.2) - actionpack (= 7.1.2) - activejob (= 7.1.2) - activerecord (= 7.1.2) - activesupport (= 7.1.2) + activerecord-enhancedsqlite3-adapter (0.8.0) + activerecord (>= 7.1) + sqlite3 (>= 1.6) + activestorage (7.2.1) + actionpack (= 7.2.1) + activejob (= 7.2.1) + activerecord (= 7.2.1) + activesupport (= 7.2.1) marcel (~> 1.0) - activesupport (7.1.2) + activesupport (7.2.1) base64 bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) - annotate (3.2.0) - activerecord (>= 3.2, < 8.0) - rake (>= 10.4, < 14.0) ast (2.4.2) base64 (0.2.0) bcrypt (3.1.20) @@ -97,7 +93,7 @@ GEM rack-test (>= 0.6.3) regexp_parser (>= 1.5, < 3.0) xpath (~> 3.2) - concurrent-ruby (1.2.2) + concurrent-ruby (1.3.4) connection_pool (2.4.1) crass (1.0.6) date (3.3.4) @@ -111,15 +107,16 @@ GEM drb (2.2.0) ruby2_keywords erubi (1.12.0) + et-orbi (1.2.11) + tzinfo + fugit (1.11.1) + et-orbi (~> 1, >= 1.2.11) + raabro (~> 1.4) + geared_pagination (1.2.0) + activesupport (>= 5.0) + addressable (>= 2.5.0) globalid (1.2.1) activesupport (>= 6.1) - hanami-router (0.6.2) - hanami-utils (~> 0.7) - http_router (~> 0.11) - hanami-utils (0.9.2) - http_router (0.11.2) - rack (>= 1.0.0) - url_mount (~> 0.2.1) i18n (1.14.1) concurrent-ruby (~> 1.0) importmap-rails (2.0.1) @@ -127,19 +124,13 @@ GEM activesupport (>= 6.0.0) railties (>= 6.0.0) io-console (0.7.1) - irb (1.11.1) - rdoc + irb (1.14.0) + rdoc (>= 4.0.0) reline (>= 0.4.2) json (2.7.1) language_server-protocol (3.17.0.3) lint_roller (1.1.0) - litestack (0.4.2) - erubi - hanami-router - oj - rack - sqlite3 - tilt + logger (1.6.1) loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -148,21 +139,26 @@ GEM net-imap net-pop net-smtp - marcel (1.0.2) + marcel (1.0.4) matrix (0.4.2) method_source (1.0.0) mini_mime (1.1.5) minitest (5.21.1) + mission_control-jobs (0.3.1) + importmap-rails + irb (~> 1.13) + rails (>= 7.1) + stimulus-rails + turbo-rails msgpack (1.7.2) - mutex_m (0.2.0) - net-imap (0.4.9.1) + net-imap (0.4.16) date net-protocol net-pop (0.1.2) net-protocol net-protocol (0.2.2) timeout - net-smtp (0.4.0.1) + net-smtp (0.5.0) net-protocol nio4r (2.7.0) nokogiri (1.16.0-aarch64-linux) @@ -171,8 +167,6 @@ GEM racc (~> 1.4) nokogiri (1.16.0-x86_64-linux) racc (~> 1.4) - oj (3.16.3) - bigdecimal (>= 3.0) parallel (1.24.0) parser (3.3.0.3) ast (~> 2.4.1) @@ -187,6 +181,7 @@ GEM public_suffix (5.0.4) puma (6.4.2) nio4r (~> 2.0) + raabro (1.4.0) racc (1.7.3) rack (3.0.8) rack-session (2.0.0) @@ -196,20 +191,20 @@ GEM rackup (2.1.0) rack (>= 3) webrick (~> 1.8) - rails (7.1.2) - actioncable (= 7.1.2) - actionmailbox (= 7.1.2) - actionmailer (= 7.1.2) - actionpack (= 7.1.2) - actiontext (= 7.1.2) - actionview (= 7.1.2) - activejob (= 7.1.2) - activemodel (= 7.1.2) - activerecord (= 7.1.2) - activestorage (= 7.1.2) - activesupport (= 7.1.2) + rails (7.2.1) + actioncable (= 7.2.1) + actionmailbox (= 7.2.1) + actionmailer (= 7.2.1) + actionpack (= 7.2.1) + actiontext (= 7.2.1) + actionview (= 7.2.1) + activejob (= 7.2.1) + activemodel (= 7.2.1) + activerecord (= 7.2.1) + activestorage (= 7.2.1) + activesupport (= 7.2.1) bundler (>= 1.15.0) - railties (= 7.1.2) + railties (= 7.2.1) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest @@ -217,10 +212,10 @@ GEM rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) - railties (7.1.2) - actionpack (= 7.1.2) - activesupport (= 7.1.2) - irb + railties (7.2.1) + actionpack (= 7.2.1) + activesupport (= 7.2.1) + irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) @@ -252,10 +247,21 @@ GEM ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) rubyzip (2.3.2) + securerandom (0.3.1) selenium-webdriver (4.16.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) + solid_cache (1.0.6) + activejob (>= 7.2) + activerecord (>= 7.2) + railties (>= 7.2) + solid_queue (0.6.1) + activejob (>= 7.1) + activerecord (>= 7.1) + concurrent-ruby (>= 1.3.1) + fugit (~> 1.11.0) + railties (>= 7.1) sqlite3 (1.7.0-aarch64-linux) sqlite3 (1.7.0-arm64-darwin) sqlite3 (1.7.0-x86_64-linux) @@ -275,7 +281,6 @@ GEM railties (>= 6.0.0) stringio (3.1.0) thor (1.3.0) - tilt (2.3.0) timeout (0.4.1) turbo-rails (1.5.0) actionpack (>= 6.0.0) @@ -284,8 +289,7 @@ GEM tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) - url_mount (0.2.1) - rack + useragent (0.16.10) view_component (3.10.0) activesupport (>= 5.2.0, < 8.0) concurrent-ruby (~> 1.0) @@ -307,31 +311,34 @@ GEM PLATFORMS aarch64-linux arm64-darwin-23 + arm64-darwin-24 x86_64-linux DEPENDENCIES - annotate + activerecord-enhancedsqlite3-adapter (~> 0.8.0) bcrypt bootsnap capybara debug dotenv-rails + geared_pagination importmap-rails - litestack + mission_control-jobs propshaft - puma (>= 5.0) - rails (~> 7.1) + puma + rails (~> 7.2) selenium-webdriver - sqlite3 (~> 1.4) + solid_cache + solid_queue + sqlite3 standard stimulus-rails turbo-rails - tzinfo-data view_component web-console RUBY VERSION - ruby 3.2.2p53 + ruby 3.3.4p94 BUNDLED WITH 2.4.19 diff --git a/app/controllers/public_controller.rb b/app/controllers/public_controller.rb new file mode 100644 index 0000000..2857026 --- /dev/null +++ b/app/controllers/public_controller.rb @@ -0,0 +1,2 @@ +class PublicController < ApplicationController +end diff --git a/app/models/blacklisted_email.rb b/app/models/blacklisted_email.rb index 4cfd3e4..a451a55 100644 --- a/app/models/blacklisted_email.rb +++ b/app/models/blacklisted_email.rb @@ -1,12 +1,4 @@ -# == Schema Information -# -# Table name: blacklisted_emails -# -# id :integer not null, primary key -# address :string not null -# reason :string not null -# created_at :datetime not null -# updated_at :datetime not null -# class BlacklistedEmail < ApplicationRecord + validates :address, presence: true, uniqueness: true + validates :reason, presence: true end diff --git a/app/models/client.rb b/app/models/client.rb index 211288a..cf34f56 100644 --- a/app/models/client.rb +++ b/app/models/client.rb @@ -1,20 +1,13 @@ -# == Schema Information -# -# Table name: clients -# -# id :integer not null, primary key -# name :string not null -# password :string not null -# state :integer default(0), not null -# username :string not null -# created_at :datetime not null -# updated_at :datetime not null -# -# Indexes -# -# index_clients_on_name (name) UNIQUE -# index_clients_on_password (password) -# index_clients_on_username (username) -# class Client < ApplicationRecord + has_many :environments + has_many :messages + has_many :recipients, through: :messages + + validates :name, presence: true, uniqueness: true + validates :state, presence: true + + enum :state, %w[active inactive].index_by(&:itself), default: :active + + encrypts :key, deterministic: true + encrypts :secret, deterministic: true end diff --git a/app/models/environment.rb b/app/models/environment.rb index f9d6e21..a96626a 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -1,25 +1,13 @@ -# == Schema Information -# -# Table name: environments -# -# id :integer not null, primary key -# name :string not null -# regex :boolean default(FALSE), not null -# reoute_address :string -# reply_to_address :string -# status :integer not null -# created_at :datetime not null -# updated_at :datetime not null -# client_id :integer not null -# -# Indexes -# -# index_environments_on_client_id (client_id) -# index_environments_on_client_id_and_name (client_id,name) UNIQUE -# -# Foreign Keys -# -# client_id (client_id => clients.id) -# class Environment < ApplicationRecord + belongs_to :client + + validates :name, presence: true, uniqueness: {scope: %i[client]} + + # approved: Messages are delivered without any filtering + # hold: Messages are saved but not delivered + # ignored: Messages are not saved but no error is returned + # rejected: Messages are not saved and an error is returned + # rerouted: Messages are sent to the Client owner + # whitelisted: Messages are only delivered to recipeints whitelisted for the Client + enum :state, %w[approved hold ignored rejected rerouted whitelisted].index_by(&:itself), default: :hold end diff --git a/app/models/message.rb b/app/models/message.rb index b2dd7dc..2a799da 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -1,28 +1,4 @@ -# == Schema Information -# -# Table name: messages -# -# id :integer not null, primary key -# content_type :string -# environment :string -# html_body :string -# priority :string -# sender :string -# sent_at :datetime -# subject :string not null -# text_body :string -# created_at :datetime not null -# updated_at :datetime not null -# client_id :integer not null -# tracking_id :string -# -# Indexes -# -# index_messages_on_client_id (client_id) -# -# Foreign Keys -# -# client_id (client_id => clients.id) -# class Message < ApplicationRecord + encrypts :html_body + encrypts :text_body end diff --git a/app/models/recipient.rb b/app/models/recipient.rb index ed612e2..a2ff7d0 100644 --- a/app/models/recipient.rb +++ b/app/models/recipient.rb @@ -1,23 +1,3 @@ -# == Schema Information -# -# Table name: recipients -# -# id :integer not null, primary key -# delivered_at :datetime -# email_address :string not null -# recipient_type :string -# send_at :datetime -# created_at :datetime not null -# updated_at :datetime not null -# message_id :integer not null -# -# Indexes -# -# index_recipients_on_message_id (message_id) -# -# Foreign Keys -# -# message_id (message_id => messages.id) -# class Recipient < ApplicationRecord + encrypts :email_address, deterministic: true end diff --git a/app/views/public/index.html.erb b/app/views/public/index.html.erb new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/app/views/public/index.html.erb @@ -0,0 +1 @@ +test diff --git a/bin/jobs b/bin/jobs new file mode 100755 index 0000000..dcf59f3 --- /dev/null +++ b/bin/jobs @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby + +require_relative "../config/environment" +require "solid_queue/cli" + +SolidQueue::Cli.start(ARGV) diff --git a/bin/setup b/bin/setup index 3cd5a9d..4a12849 100755 --- a/bin/setup +++ b/bin/setup @@ -3,6 +3,7 @@ require "fileutils" # path to your application root. APP_ROOT = File.expand_path("..", __dir__) +APP_NAME = "hermes" def system!(*args) system(*args, exception: true) @@ -30,4 +31,8 @@ FileUtils.chdir APP_ROOT do puts "\n== Restarting application server ==" system! "bin/rails restart" + + puts "\n== Configuring puma-dev ==" + system "ln -nfs #{APP_ROOT} ~/.puma-dev/#{APP_NAME}" + system "curl -Is https://#{APP_NAME}.test/up | head -n 1" end diff --git a/config/application.rb b/config/application.rb index 19eb594..f82c2c9 100644 --- a/config/application.rb +++ b/config/application.rb @@ -21,7 +21,7 @@ module Hermes class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 7.1 + config.load_defaults 7.2 # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. diff --git a/config/cache.yml b/config/cache.yml new file mode 100644 index 0000000..acd5ca5 --- /dev/null +++ b/config/cache.yml @@ -0,0 +1,17 @@ +default: &default + store_options: + # Cap age of oldest cache entry to fulfill retention policies + # max_age: <%= 60.days.to_i %> + max_size: <%= 256.megabytes %> + namespace: <%= Rails.env %> + +development: + <<: *default + +test: + <<: *default + +production: + database: cache + <<: *default + encrypt: true diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc index 632cdb0..7a89a3f 100644 --- a/config/credentials.yml.enc +++ b/config/credentials.yml.enc @@ -1 +1 @@ -hWUoir6sawOIqpseQHn+TBgp/PhfIFw+Bv4MPHRkBKHVAS8/f0JDwDaCx+EUohLenXVgs5ovXb/6CkE1RC/5FHEdtMRa58DqwU3xheglkQ2tQvPQ/20KtiNjnO+Clf4hovVMwH+0KqKFXdELxuQHqAu0muXjw0Dzi0ZdA0jMeEmxbxTVggoRygpwroNNfrOcxKYWd1zZibBq0NDKVFHn9nr+dKSC3NTq2HswfMgsTgVia27M5paTyRV7a8A/r9GGM/0mOrqaLEE7lFLbdKqVlL3+djyMxo/y3pj+8iBBPsgM/WX0YHxg0GMfSF7BRt5L7w/oKdVpdxdz3l5DOgY+1Fe8r3UsanwX7hZEda8KIAiqodsEepa7wd1lh8YCA2x0hvWUqcRgmx2af+qRIRVYe7y72GlC--v+gk1dQMsI66MUt3--ex97lsm2KWiX68X4vEIzzA== \ No newline at end of file +J5PcU2tgRC4xXCJeVJR/xl3/dg7CgOWduTbxaALTI6lJc3IbuJFmMWUSlNqyx+4r1OcJazjZKmZg891BwztR0L+BhTzOSheAdkWzZTN3i0L9daB/aztdSZDmRG9ss7Hhahk0MT4qR62qy8WlEhoNpqe9SWweJyiVKcbP4FVi1Cs6dibz5UhQg9VnOWg+9C/Rj7wICwqzFUFZAkQdfW2ifVLyq4bvOI2/KNket+RRx5IiT1nCy+759muX1LFTJYzbfQC5UbGDEZ+xKFDOiURLU8PW+4IegR6exCsjiSjx9FPxWxZ571EqYPtJGhHG+ChzTd/WDrHTMchtPHs9AeJtliCC3heoSA2hIyjoMLuObf9vmK0QnxZEiEbBJGdEg5f2DTLIvtw3DTHy7sUn1V9Y4tkUYhfGPwaZxgxgtVEU9WPqRSQG6X0gA1Cmyxdw6kOR--5ZhY5XQUX0nUoy2S--/JH70GypbNmm3CQPCkE6cQ== \ No newline at end of file diff --git a/config/database.yml b/config/database.yml index 98790da..2509c07 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,39 +1,45 @@ -# SQLite. Versions 3.8.0 and up are supported. -# gem install sqlite3 -# -# Ensure the SQLite 3 gem is defined in your Gemfile -# gem "sqlite3" -# -# `Litesupport.root.join("data.sqlite3")` stores -# application data in the path `./db/#{Rails.env}/data.sqlite3` -# -# `Litesupport.root(env).join(path)` stores -# application data in the path `./db/#{env}/#{path}` -# -# idle_timeout should be set to zero, to avoid recycling sqlite connections -# and losing the page cache -# default: &default - adapter: litedb - pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> - idle_timeout: 0 + adapter: sqlite3 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 3 } %> + timeout: 5000 + retries: 100 + default_transaction_mode: immediate development: - <<: *default - database: <%= Litesupport.root("development").join("data.sqlite3") %> + primary: + <<: *default + database: storage/db/development.sqlite3 + queue: + <<: *default + database: storage/db/development_queue.sqlite3 + migrations_paths: db/queue_migrate + cache: + <<: *default + database: storage/db/development_cache.sqlite3 + migrations_paths: db/cache_migrate -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. test: - <<: *default - database: <%= Litesupport.root("test").join("data.sqlite3") %> + primary: + <<: *default + database: storage/db/test.sqlite3 + queue: + <<: *default + database: storage/db/test_queue.sqlite3 + migrations_paths: db/queue_migrate + cache: + <<: *default + database: storage/db/test_cache.sqlite3 + migrations_paths: db/cache_migrate -# Warning: Make sure your production database path is on a persistent -# volume, otherwise your application data could be deleted between deploys. -# -# You may also set the Litesupport.root in production via the -# `LITESTACK_DATA_PATH` environment variable. production: - <<: *default - database: <%= Litesupport.root("production").join("data.sqlite3") %> + primary: + <<: *default + database: storage/db/production.sqlite3 + queue: + <<: *default + database: storage/db/production_queue.sqlite3 + migrations_paths: db/queue_migrate + cache: + <<: *default + database: storage/db/production_cache.sqlite3 + migrations_paths: db/cache_migrate diff --git a/config/environments/development.rb b/config/environments/development.rb index f4f02c6..5e2daab 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -2,7 +2,7 @@ Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - config.hosts << "hermes.mythcoders.test" + config.hosts << "hermes.test" # In the development environment your application's code is reloaded any time # it changes. This slows down response time but is perfect for development @@ -24,7 +24,7 @@ config.action_controller.perform_caching = true config.action_controller.enable_fragment_cache_logging = true - config.cache_store = :memory_store + config.cache_store = :solid_cache_store config.public_file_server.headers = { "Cache-Control" => "public, max-age=#{2.days.to_i}" } @@ -60,8 +60,9 @@ # Highlight code that enqueued background job in logs. config.active_job.verbose_enqueue_logs = true - config.active_job.queue_adapter = :litejob - config.active_job.queue_name_prefix = "hermes_development" + config.active_job.queue_adapter = :solid_queue + config.active_job.queue_name_prefix = Rails.env + config.solid_queue.connects_to = {database: {writing: :queue}} # Raises error for missing translations. # config.i18n.raise_on_missing_translations = true diff --git a/config/environments/production.rb b/config/environments/production.rb index 219aa2d..54977a3 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -59,11 +59,12 @@ config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") # Use a different cache store in production. - config.cache_store = :litecache + config.cache_store = :solid_cache_store # Use a real queuing backend for Active Job (and separate queues per environment). - config.active_job.queue_adapter = :litejob - config.active_job.queue_name_prefix = "hermes_production" + config.active_job.queue_adapter = :solid_queue + config.active_job.queue_name_prefix = Rails.env + config.solid_queue.connects_to = {database: {writing: :queue}} config.action_mailer.perform_caching = false diff --git a/config/environments/test.rb b/config/environments/test.rb index adbb4a6..b2bc4f2 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -61,4 +61,5 @@ # Raise error when a before_action's only/except options reference missing actions config.action_controller.raise_on_missing_callback_actions = true + config.active_record.encryption.encrypt_fixtures = true end diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index c2d89e2..c010b83 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -4,5 +4,5 @@ # Use this to limit dissemination of sensitive information. # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors. Rails.application.config.filter_parameters += [ - :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn + :passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn ] diff --git a/config/puma.rb b/config/puma.rb index afa809b..60e1b9c 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -2,34 +2,32 @@ # are invoked here are part of Puma's configuration DSL. For more information # about methods provided by the DSL, see https://puma.io/puma/Puma/DSL.html. -# Puma can serve each request in a thread from an internal thread pool. -# The `threads` method setting takes two numbers: a minimum and maximum. -# Any libraries that use thread pools should be configured to match -# the maximum value specified for Puma. Default is set to 5 threads for minimum -# and maximum; this matches the default thread size of Active Record. -max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } -min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } -threads min_threads_count, max_threads_count - -# Specifies that the worker count should equal the number of processors in production. -if ENV["RAILS_ENV"] == "production" - require "concurrent-ruby" - worker_count = Integer(ENV.fetch("WEB_CONCURRENCY") { Concurrent.physical_processor_count }) - workers worker_count if worker_count > 1 -end - -# Specifies the `worker_timeout` threshold that Puma will use to wait before -# terminating a worker in development environments. -worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" +# Puma starts a configurable number of processes (workers) and each process +# serves each request in a thread from an internal thread pool. +# +# The ideal number of threads per worker depends both on how much time the +# application spends waiting for IO operations and on how much you wish to +# to prioritize throughput over latency. +# +# As a rule of thumb, increasing the number of threads will increase how much +# traffic a given process can handle (throughput), but due to CRuby's +# Global VM Lock (GVL) it has diminishing returns and will degrade the +# response time (latency) of the application. +# +# The default is set to 3 threads as it's deemed a decent compromise between +# throughput and latency for the average Rails application. +# +# Any libraries that use a connection pool or another resource pool should +# be configured to provide at least as many connections as the number of +# threads. This includes Active Record's `pool` parameter in `database.yml`. +threads_count = ENV.fetch("RAILS_MAX_THREADS", 3) +threads threads_count, threads_count # Specifies the `port` that Puma will listen on to receive requests; default is 3000. -port ENV.fetch("PORT") { 3000 } - -# Specifies the `environment` that Puma will run in. -environment ENV.fetch("RAILS_ENV") { "development" } - -# Specifies the `pidfile` that Puma will use. -pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } +port ENV.fetch("PORT", 3000) # Allow puma to be restarted by `bin/rails restart` command. plugin :tmp_restart + +# Only use a pidfile when requested +pidfile ENV["PIDFILE"] if ENV["PIDFILE"] diff --git a/config/queue.yml b/config/queue.yml new file mode 100644 index 0000000..15691e9 --- /dev/null +++ b/config/queue.yml @@ -0,0 +1,18 @@ +default: &default + dispatchers: + - polling_interval: 1 + batch_size: 500 + workers: + - queues: "*" + threads: 3 + processes: <%%= ENV.fetch("JOB_CONCURRENCY", 1) %> + polling_interval: 0.1 + +development: + <<: *default + +test: + <<: *default + +production: + <<: *default diff --git a/config/routes.rb b/config/routes.rb index 9f768e5..b3d65d5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,10 +1,7 @@ Rails.application.routes.draw do - # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html - - # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. - # Can be used by load balancers and uptime monitors to verify that the app is live. get "up" => "rails/health#show", :as => :rails_health_check - # Defines the root path route ("/") - # root "posts#index" + root "public#index" + + mount MissionControl::Jobs::Engine, at: "/jobs" end diff --git a/db/cache_schema.rb b/db/cache_schema.rb new file mode 100644 index 0000000..d37677e --- /dev/null +++ b/db/cache_schema.rb @@ -0,0 +1,14 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema[7.2].define(version: 0) do +end diff --git a/db/migrate/20240115065325_create_clients.rb b/db/migrate/20240115065325_create_clients.rb index 57d65ae..e083c16 100644 --- a/db/migrate/20240115065325_create_clients.rb +++ b/db/migrate/20240115065325_create_clients.rb @@ -1,17 +1,17 @@ -class CreateClients < ActiveRecord::Migration[7.1] +class CreateClients < ActiveRecord::Migration[7.2] def change create_table :clients do |t| t.string :name, null: false, index: {unique: true} - t.integer :state, null: false, default: 0 - t.string :username, null: false, index: true - t.string :password, null: false, index: true + t.string :state, null: false + t.string :key, null: false, index: true + t.string :secret, null: false, index: true t.timestamps end create_table :environments do |t| t.references :client, null: false, foreign_key: true t.string :name, null: false - t.integer :status, null: false + t.string :state, null: false t.boolean :regex, default: false, null: false t.string :reoute_address t.string :reply_to_address diff --git a/db/migrate/20240115065341_create_messages.rb b/db/migrate/20240115065341_create_messages.rb index 79575f2..e478abd 100644 --- a/db/migrate/20240115065341_create_messages.rb +++ b/db/migrate/20240115065341_create_messages.rb @@ -1,4 +1,4 @@ -class CreateMessages < ActiveRecord::Migration[7.1] +class CreateMessages < ActiveRecord::Migration[7.2] def change create_table :callbacks do |t| t.string :data, null: false @@ -8,54 +8,32 @@ def change create_table :messages do |t| t.references :client, null: false, foreign_key: true - t.string :tracking_id + t.string :uuid, null: false, index: {unique: true} t.string :sender - t.string :subject, null: false + t.string :subject t.string :html_body + t.string :text_body t.string :content_type t.string :priority t.string :environment - t.string :text_body - t.datetime :sent_at + t.datetime :scheduled_at t.timestamps end create_table :recipients do |t| t.references :message, null: false, foreign_key: true + t.string :uuid, null: false, index: {unique: true} t.string :recipient_type t.string :email_address, null: false - t.datetime :send_at + t.datetime :sent_at t.datetime :delivered_at - t.timestamps - end - - create_table :message_activities do |t| - t.references :message, null: false, foreign_key: true, index: true - t.references :recipient, null: true, foreign_key: true, index: true - t.string :activity_type - t.string :activity_details - t.string :ip_address - t.string :user_agent - t.string :link_url - t.string :reject_reason - t.string :reporting_mta - t.string :smtp_response - t.string :bounce_type - t.string :feedback_id - t.string :complaint_type - t.datetime :complaint_arrival_date - t.datetime :notification_timestamp - t.string :bounce_subtype - t.string :delay_type - t.datetime :expiration_time - t.string :action - t.string :status - t.string :diagnostic_code + t.datetime :opened_at + t.datetime :clicked_at t.timestamps end create_table :blacklisted_emails do |t| - t.string :address, null: false + t.string :address, null: false, index: {unique: true} t.string :reason, null: false t.timestamps end diff --git a/db/queue_migrate/20240912011306_create_solid_queue_tables.solid_queue.rb b/db/queue_migrate/20240912011306_create_solid_queue_tables.solid_queue.rb new file mode 100644 index 0000000..6d8c4f6 --- /dev/null +++ b/db/queue_migrate/20240912011306_create_solid_queue_tables.solid_queue.rb @@ -0,0 +1,101 @@ +# This migration comes from solid_queue (originally 20231211200639) +class CreateSolidQueueTables < ActiveRecord::Migration[7.0] + def change + create_table :solid_queue_jobs do |t| + t.string :queue_name, null: false + t.string :class_name, null: false, index: true + t.text :arguments + t.integer :priority, default: 0, null: false + t.string :active_job_id, index: true + t.datetime :scheduled_at + t.datetime :finished_at, index: true + t.string :concurrency_key + + t.timestamps + + t.index [ :queue_name, :finished_at ], name: "index_solid_queue_jobs_for_filtering" + t.index [ :scheduled_at, :finished_at ], name: "index_solid_queue_jobs_for_alerting" + end + + create_table :solid_queue_scheduled_executions do |t| + t.references :job, index: { unique: true }, null: false + t.string :queue_name, null: false + t.integer :priority, default: 0, null: false + t.datetime :scheduled_at, null: false + + t.datetime :created_at, null: false + + t.index [ :scheduled_at, :priority, :job_id ], name: "index_solid_queue_dispatch_all" + end + + create_table :solid_queue_ready_executions do |t| + t.references :job, index: { unique: true }, null: false + t.string :queue_name, null: false + t.integer :priority, default: 0, null: false + + t.datetime :created_at, null: false + + t.index [ :priority, :job_id ], name: "index_solid_queue_poll_all" + t.index [ :queue_name, :priority, :job_id ], name: "index_solid_queue_poll_by_queue" + end + + create_table :solid_queue_claimed_executions do |t| + t.references :job, index: { unique: true }, null: false + t.bigint :process_id + t.datetime :created_at, null: false + + t.index [ :process_id, :job_id ] + end + + create_table :solid_queue_blocked_executions do |t| + t.references :job, index: { unique: true }, null: false + t.string :queue_name, null: false + t.integer :priority, default: 0, null: false + t.string :concurrency_key, null: false + t.datetime :expires_at, null: false + + t.datetime :created_at, null: false + + t.index [ :expires_at, :concurrency_key ], name: "index_solid_queue_blocked_executions_for_maintenance" + end + + create_table :solid_queue_failed_executions do |t| + t.references :job, index: { unique: true }, null: false + t.text :error + t.datetime :created_at, null: false + end + + create_table :solid_queue_pauses do |t| + t.string :queue_name, null: false, index: { unique: true } + t.datetime :created_at, null: false + end + + create_table :solid_queue_processes do |t| + t.string :kind, null: false + t.datetime :last_heartbeat_at, null: false, index: true + t.bigint :supervisor_id, index: true + + t.integer :pid, null: false + t.string :hostname + t.text :metadata + + t.datetime :created_at, null: false + end + + create_table :solid_queue_semaphores do |t| + t.string :key, null: false, index: { unique: true } + t.integer :value, default: 1, null: false + t.datetime :expires_at, null: false, index: true + + t.timestamps + + t.index [ :key, :value ], name: "index_solid_queue_semaphores_on_key_and_value" + end + + add_foreign_key :solid_queue_blocked_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + add_foreign_key :solid_queue_claimed_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + add_foreign_key :solid_queue_failed_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + add_foreign_key :solid_queue_ready_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + add_foreign_key :solid_queue_scheduled_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + end +end diff --git a/db/queue_migrate/20240912011307_add_missing_index_to_blocked_executions.solid_queue.rb b/db/queue_migrate/20240912011307_add_missing_index_to_blocked_executions.solid_queue.rb new file mode 100644 index 0000000..2d96b10 --- /dev/null +++ b/db/queue_migrate/20240912011307_add_missing_index_to_blocked_executions.solid_queue.rb @@ -0,0 +1,6 @@ +# This migration comes from solid_queue (originally 20240110143450) +class AddMissingIndexToBlockedExecutions < ActiveRecord::Migration[7.1] + def change + add_index :solid_queue_blocked_executions, [ :concurrency_key, :priority, :job_id ], name: "index_solid_queue_blocked_executions_for_release" + end +end diff --git a/db/queue_migrate/20240912011308_create_recurring_executions.solid_queue.rb b/db/queue_migrate/20240912011308_create_recurring_executions.solid_queue.rb new file mode 100644 index 0000000..4c49821 --- /dev/null +++ b/db/queue_migrate/20240912011308_create_recurring_executions.solid_queue.rb @@ -0,0 +1,15 @@ +# This migration comes from solid_queue (originally 20240218110712) +class CreateRecurringExecutions < ActiveRecord::Migration[7.1] + def change + create_table :solid_queue_recurring_executions do |t| + t.references :job, index: { unique: true }, null: false + t.string :task_key, null: false + t.datetime :run_at, null: false + t.datetime :created_at, null: false + + t.index [ :task_key, :run_at ], unique: true + end + + add_foreign_key :solid_queue_recurring_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade + end +end diff --git a/db/queue_migrate/20240912011309_create_recurring_tasks.solid_queue.rb b/db/queue_migrate/20240912011309_create_recurring_tasks.solid_queue.rb new file mode 100644 index 0000000..507c9e7 --- /dev/null +++ b/db/queue_migrate/20240912011309_create_recurring_tasks.solid_queue.rb @@ -0,0 +1,21 @@ +# This migration comes from solid_queue (originally 20240719134516) +class CreateRecurringTasks < ActiveRecord::Migration[7.1] + def change + create_table :solid_queue_recurring_tasks do |t| + t.string :key, null: false, index: { unique: true } + t.string :schedule, null: false + t.string :command, limit: 2048 + t.string :class_name + t.text :arguments + + t.string :queue_name + t.integer :priority, default: 0 + + t.boolean :static, default: true, index: true + + t.text :description + + t.timestamps + end + end +end diff --git a/db/queue_migrate/20240912011310_add_name_to_processes.solid_queue.rb b/db/queue_migrate/20240912011310_add_name_to_processes.solid_queue.rb new file mode 100644 index 0000000..d5c14cd --- /dev/null +++ b/db/queue_migrate/20240912011310_add_name_to_processes.solid_queue.rb @@ -0,0 +1,6 @@ +# This migration comes from solid_queue (originally 20240811173327) +class AddNameToProcesses < ActiveRecord::Migration[7.1] + def change + add_column :solid_queue_processes, :name, :string + end +end diff --git a/db/queue_migrate/20240912011311_make_name_not_null.solid_queue.rb b/db/queue_migrate/20240912011311_make_name_not_null.solid_queue.rb new file mode 100644 index 0000000..f56dd4d --- /dev/null +++ b/db/queue_migrate/20240912011311_make_name_not_null.solid_queue.rb @@ -0,0 +1,17 @@ +# This migration comes from solid_queue (originally 20240813160053) +class MakeNameNotNull < ActiveRecord::Migration[7.1] + def up + SolidQueue::Process.where(name: nil).find_each do |process| + process.name ||= [ process.kind.downcase, SecureRandom.hex(10) ].join("-") + process.save! + end + + change_column :solid_queue_processes, :name, :string, null: false + add_index :solid_queue_processes, [ :name, :supervisor_id ], unique: true + end + + def down + remove_index :solid_queue_processes, [ :name, :supervisor_id ] + change_column :solid_queue_processes, :name, :string, null: true + end +end diff --git a/db/queue_migrate/20240912011312_change_solid_queue_recurring_tasks_static_to_not_null.solid_queue.rb b/db/queue_migrate/20240912011312_change_solid_queue_recurring_tasks_static_to_not_null.solid_queue.rb new file mode 100644 index 0000000..325320a --- /dev/null +++ b/db/queue_migrate/20240912011312_change_solid_queue_recurring_tasks_static_to_not_null.solid_queue.rb @@ -0,0 +1,6 @@ +# This migration comes from solid_queue (originally 20240819165045) +class ChangeSolidQueueRecurringTasksStaticToNotNull < ActiveRecord::Migration[7.1] + def change + change_column_null :solid_queue_recurring_tasks, :static, false, true + end +end diff --git a/db/queue_schema.rb b/db/queue_schema.rb new file mode 100644 index 0000000..718d5e6 --- /dev/null +++ b/db/queue_schema.rb @@ -0,0 +1,141 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema[7.2].define(version: 2024_09_12_011312) do + create_table "solid_queue_blocked_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.string "concurrency_key", null: false + t.datetime "expires_at", null: false + t.datetime "created_at", null: false + t.index ["concurrency_key", "priority", "job_id"], name: "index_solid_queue_blocked_executions_for_release" + t.index ["expires_at", "concurrency_key"], name: "index_solid_queue_blocked_executions_for_maintenance" + t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true + end + + create_table "solid_queue_claimed_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.bigint "process_id" + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true + t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id" + end + + create_table "solid_queue_failed_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.text "error" + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true + end + + create_table "solid_queue_jobs", force: :cascade do |t| + t.string "queue_name", null: false + t.string "class_name", null: false + t.text "arguments" + t.integer "priority", default: 0, null: false + t.string "active_job_id" + t.datetime "scheduled_at" + t.datetime "finished_at" + t.string "concurrency_key" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["active_job_id"], name: "index_solid_queue_jobs_on_active_job_id" + t.index ["class_name"], name: "index_solid_queue_jobs_on_class_name" + t.index ["finished_at"], name: "index_solid_queue_jobs_on_finished_at" + t.index ["queue_name", "finished_at"], name: "index_solid_queue_jobs_for_filtering" + t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting" + end + + create_table "solid_queue_pauses", force: :cascade do |t| + t.string "queue_name", null: false + t.datetime "created_at", null: false + t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true + end + + create_table "solid_queue_processes", force: :cascade do |t| + t.string "kind", null: false + t.datetime "last_heartbeat_at", null: false + t.bigint "supervisor_id" + t.integer "pid", null: false + t.string "hostname" + t.text "metadata" + t.datetime "created_at", null: false + t.string "name", null: false + t.index ["last_heartbeat_at"], name: "index_solid_queue_processes_on_last_heartbeat_at" + t.index ["name", "supervisor_id"], name: "index_solid_queue_processes_on_name_and_supervisor_id", unique: true + t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id" + end + + create_table "solid_queue_ready_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_ready_executions_on_job_id", unique: true + t.index ["priority", "job_id"], name: "index_solid_queue_poll_all" + t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue" + end + + create_table "solid_queue_recurring_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "task_key", null: false + t.datetime "run_at", null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_recurring_executions_on_job_id", unique: true + t.index ["task_key", "run_at"], name: "index_solid_queue_recurring_executions_on_task_key_and_run_at", unique: true + end + + create_table "solid_queue_recurring_tasks", force: :cascade do |t| + t.string "key", null: false + t.string "schedule", null: false + t.string "command", limit: 2048 + t.string "class_name" + t.text "arguments" + t.string "queue_name" + t.integer "priority", default: 0 + t.boolean "static", default: true, null: false + t.text "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["key"], name: "index_solid_queue_recurring_tasks_on_key", unique: true + t.index ["static"], name: "index_solid_queue_recurring_tasks_on_static" + end + + create_table "solid_queue_scheduled_executions", force: :cascade do |t| + t.integer "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.datetime "scheduled_at", null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true + t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all" + end + + create_table "solid_queue_semaphores", force: :cascade do |t| + t.string "key", null: false + t.integer "value", default: 1, null: false + t.datetime "expires_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["expires_at"], name: "index_solid_queue_semaphores_on_expires_at" + t.index ["key", "value"], name: "index_solid_queue_semaphores_on_key_and_value" + t.index ["key"], name: "index_solid_queue_semaphores_on_key", unique: true + end + + add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_recurring_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade +end diff --git a/db/schema.rb b/db/schema.rb index f038627..9606682 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,12 +10,13 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_01_15_065341) do +ActiveRecord::Schema[7.2].define(version: 2024_01_15_065341) do create_table "blacklisted_emails", force: :cascade do |t| t.string "address", null: false t.string "reason", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["address"], name: "index_blacklisted_emails_on_address", unique: true end create_table "callbacks", force: :cascade do |t| @@ -27,20 +28,20 @@ create_table "clients", force: :cascade do |t| t.string "name", null: false - t.integer "state", default: 0, null: false - t.string "username", null: false - t.string "password", null: false + t.string "state", null: false + t.string "key", null: false + t.string "secret", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["key"], name: "index_clients_on_key" t.index ["name"], name: "index_clients_on_name", unique: true - t.index ["password"], name: "index_clients_on_password" - t.index ["username"], name: "index_clients_on_username" + t.index ["secret"], name: "index_clients_on_secret" end create_table "environments", force: :cascade do |t| t.integer "client_id", null: false t.string "name", null: false - t.integer "status", null: false + t.string "state", null: false t.boolean "regex", default: false, null: false t.string "reoute_address" t.string "reply_to_address" @@ -50,64 +51,39 @@ t.index ["client_id"], name: "index_environments_on_client_id" end - create_table "message_activities", force: :cascade do |t| - t.integer "message_id", null: false - t.integer "recipient_id" - t.string "activity_type" - t.string "activity_details" - t.string "ip_address" - t.string "user_agent" - t.string "link_url" - t.string "reject_reason" - t.string "reporting_mta" - t.string "smtp_response" - t.string "bounce_type" - t.string "feedback_id" - t.string "complaint_type" - t.datetime "complaint_arrival_date" - t.datetime "notification_timestamp" - t.string "bounce_subtype" - t.string "delay_type" - t.datetime "expiration_time" - t.string "action" - t.string "status" - t.string "diagnostic_code" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["message_id"], name: "index_message_activities_on_message_id" - t.index ["recipient_id"], name: "index_message_activities_on_recipient_id" - end - create_table "messages", force: :cascade do |t| t.integer "client_id", null: false - t.string "tracking_id" + t.string "uuid", null: false t.string "sender" - t.string "subject", null: false + t.string "subject" t.string "html_body" + t.string "text_body" t.string "content_type" t.string "priority" t.string "environment" - t.string "text_body" - t.datetime "sent_at" + t.datetime "scheduled_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["client_id"], name: "index_messages_on_client_id" + t.index ["uuid"], name: "index_messages_on_uuid", unique: true end create_table "recipients", force: :cascade do |t| t.integer "message_id", null: false + t.string "uuid", null: false t.string "recipient_type" t.string "email_address", null: false - t.datetime "send_at" + t.datetime "sent_at" t.datetime "delivered_at" + t.datetime "opened_at" + t.datetime "clicked_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["message_id"], name: "index_recipients_on_message_id" + t.index ["uuid"], name: "index_recipients_on_uuid", unique: true end add_foreign_key "environments", "clients" - add_foreign_key "message_activities", "messages" - add_foreign_key "message_activities", "recipients" add_foreign_key "messages", "clients" add_foreign_key "recipients", "messages" end diff --git a/dev/mythcoders.test.crt b/dev/mythcoders.test.crt deleted file mode 100644 index fd297b2..0000000 --- a/dev/mythcoders.test.crt +++ /dev/null @@ -1,26 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEczCCAtugAwIBAgIQWSln4YRh+mPRkMcO/HhZXzANBgkqhkiG9w0BAQsFADCB -kzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTQwMgYDVQQLDCtqbWFk -a2luc0BKdXN0aW5zLWlNYWMubG9jYWwgKEp1c3RpbiBBZGtpbnMpMTswOQYDVQQD -DDJta2NlcnQgam1hZGtpbnNASnVzdGlucy1pTWFjLmxvY2FsIChKdXN0aW4gQWRr -aW5zKTAeFw0yMzA4MzEwMzQ0NThaFw0yNTEyMDEwNDQ0NThaMF4xJzAlBgNVBAoT -Hm1rY2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0ZTEzMDEGA1UECwwqamFka2lu -c0BKdXN0aW5zLU1CUC5zYW1hZGEgKEp1c3RpbiBBZGtpbnMpMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlnzdv+rpmGL79b+ZvGAR47HYc47/VwOe/HHP -6gzBd+CGrfeTi9T+ZU4psVXu19TsuyFFh8isGd2qdAbVbNsbDNA7YdupeV6R5d3l -EmqdCiEepdw64/Xra3RjT4ZKDYmJzqUQrZzg1Xsy1X+gFw0cuajH42wuh8OiXLCW -G2s7v838Sl8KhbhY9TTIb8gnSR9DrU83jkkNAqlWWUmVVjkNl+U9PJ+YkVdG8rZB -/nb6jM8dNyRh2xoWLla9ijYvG68U+teHM+iLl3ItgG1OzgLD7BLcGzWSWuLYE7Uo -FMJY9KEcEhtLBZEU+nC0ks1JsnOD3uToLyXR/M2/pf5WURfFUQIDAQABo3cwdTAO -BgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHwYDVR0jBBgwFoAU -GZqJlFARlW96cJzc/ywmAyuXREEwLQYDVR0RBCYwJIIPbXl0aGNvZGVycy50ZXN0 -ghEqLm15dGhjb2RlcnMudGVzdDANBgkqhkiG9w0BAQsFAAOCAYEAydwcmfDPiH7p -TJDLkjABvTKPe6IzXQxFAjaKv8wWSVvd14up/8TZURawRO+iX+M4w2/MYEHtGr97 -FawNKWIaq2jkMvp9ZH7iZ0f1eekTmH9Ct8kcO8ghh65zSlv0LLaIfu7koqmH/H0B -N4zHmJGt8Q2DrVX+JKyzZ301NCNOe3V0+LL1tscDYHKMDpgHLOoHMno8LV6MkDSD -V0oIDcNHUWOLZV7omxncnq1q5MidRv0X2a/MapYBrj/KpFIyKYU3A9FLJJD22OEB -GKRuLBhFyMoScVcrpvPACqI8ceBb9htNRmJwvDEd8yyvUSYtY4PojbbGM4R7Xt60 -k8VBBmhH2jsSwh7bqv0EUIpHgp7bWV4moXVi3HM0UjPYCWzfxoGVs3glFhinb5R4 -v+M7Z5a5U0t/G+953EfJqsopKza0oDT+nbmEmuLBF2K/ou7DzXY4/pW2V5CFGeE2 -cFyKzgIZ+wjw4zFOp/lwbNXXiufdVJFdMi7jEA2l0gtbfS1KLRsv ------END CERTIFICATE----- diff --git a/dev/mythcoders.test.key b/dev/mythcoders.test.key deleted file mode 100644 index 62970ba..0000000 --- a/dev/mythcoders.test.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCWfN2/6umYYvv1 -v5m8YBHjsdhzjv9XA578cc/qDMF34Iat95OL1P5lTimxVe7X1Oy7IUWHyKwZ3ap0 -BtVs2xsM0Dth26l5XpHl3eUSap0KIR6l3Drj9etrdGNPhkoNiYnOpRCtnODVezLV -f6AXDRy5qMfjbC6Hw6JcsJYbazu/zfxKXwqFuFj1NMhvyCdJH0OtTzeOSQ0CqVZZ -SZVWOQ2X5T08n5iRV0bytkH+dvqMzx03JGHbGhYuVr2KNi8brxT614cz6IuXci2A -bU7OAsPsEtwbNZJa4tgTtSgUwlj0oRwSG0sFkRT6cLSSzUmyc4Pe5OgvJdH8zb+l -/lZRF8VRAgMBAAECggEAc0xQCc7OErckHHEkNLPWgQGtuTwCXoSjtv7sMYJ8aIBa -L8fT//q8vplYUEpqqGq2xdkEELirQ1YWVrc1piVpYDPai2tlOVw/pEKSU73je/NM -K//EDwxHxxhxTmixLBYIw46sbJgZmva9R950pbSiIY0zOQeVzucQ6rtRBsjuClF2 -/vEQiXStrSZcr1cFk8RaWEXT8xkSprZzUXpqLfACWPG61olSmjChX2eUng4QxaiE -cWo6QZeMxrp4//385Y2GT7buuOviGAV86VyFwCCrN5hhZr4HGkcpbuSOXWZgHPuH -tVDh7kCtulof351xSY1kulgyrYDLjm2fVTub/R63EQKBgQDHxsmb5wvpATJl8/UD -T77PkOHhvfywYKyWBEkZxKtw+ODy9LOVv9ST+NSzutZA68Etoplk9ecUuf3Gi+p/ -RDrS9yYe9ak84eOMuFMJ6RJTP+mEdxDg47KHvRrDvcND9X+dzwfgMiGLXlqK5oIk -e6V1iUzmuda6AEYcprhbkcrb3wKBgQDA1v4yQzPQYoWL6ie/pOWc0Dcwcq/P6yIf -Thmb+NsLahMjREqCQpOBcKXsx6RSAtB/9OOEkwt9yEAWCkWVrdbHmyt4b7Vui0NZ -zDHEWb20UQZcw7Ht7ku5ZTHZKhYJlFokllwqNAbL5MUWT4l72dZn3QCJqHAv3wjm -/rpmYW+EzwKBgQCaoAUJszHnvbJpcQJR9tYkR+pdVDSRu7G5R0XhOPTNMwTBZ57c -KCb8BNt05QbSJudVUAXUO/QIedCvbToqGQBCq2KJEfFUmy4Ji91RzWEOqGgwzAt3 -VSWopDhkCqtpHUoSNdzNrV+DRJtl6PYQENfG+mdYKbzGKFIb+Pq2fUh7FwKBgD7r -Jt8xbAt2ycn/6V4vKDfE++zTzqdROb3rFpH8XUPZJUthccoUfNpD7e9WqDeV8X9+ -YGmWLK6qkrZePZv7r1NLPqC6GgFqcNwwsqA1A598vE2yEDDoik6ARQZtI+mWPN8p -LAMdHIaUKvX/l4UQa1NSGWXQzmHgLKBpxlm3OtKjAoGBAKp+YQWXpX0VtTekI9Ik -SHB8YvGp0o03hUfqBE5Rad5nHwrgj460N+dMd4/iQpJfQpVzDm8XpXX5fcLzME5+ -xeyiQiMgPMOb/pzHfLEyq5itWcXzvmiElHnTmPoKUK84Qiwcpg4JMwUANxxhzXDG -pI7yZLvMNeFaknyboXQ8KY4P ------END PRIVATE KEY----- diff --git a/dev/nginx.conf b/dev/nginx.conf deleted file mode 100644 index 0ac55cb..0000000 --- a/dev/nginx.conf +++ /dev/null @@ -1,43 +0,0 @@ -events { } - -http { - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - - client_max_body_size 0; - - server { - listen 80; - http2 on; - server_name hermes.mythcoders.test; - return 301 https://$host$request_uri; - } - - server { - listen 443 ssl; - http2 on; - server_name hermes.mythcoders.test; - - ssl_certificate /ssl/mythcoders.test.crt; - ssl_certificate_key /ssl/mythcoders.test.key; - - access_log /var/log/nginx/access.log combined; - error_log /var/log/nginx/error.log; - - location / { - proxy_pass http://hermes-app:3000/; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_redirect http://hermes-app:3000/ $scheme://$http_host/; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_read_timeout 20d; - proxy_buffering off; - } - } -} diff --git a/dev/rules.yml b/dev/rules.yml deleted file mode 100644 index 698b124..0000000 --- a/dev/rules.yml +++ /dev/null @@ -1,6 +0,0 @@ -tls: - stores: - default: - defaultCertificate: - certFile: /etc/traefik/mythcoders.test.crt - keyFile: /etc/traefik/mythcoders.test.key diff --git a/dev/setup.yml b/dev/setup.yml deleted file mode 100644 index 8561541..0000000 --- a/dev/setup.yml +++ /dev/null @@ -1,152 +0,0 @@ ---- -- hosts: localhost - gather_facts: false - connection: local - vars: - network_name: hermes - handlers: - - name: restart dnsmasq - become: yes - command: brew services restart dnsmasq - - name: setup mkcert - become: yes - command: mkcert --install - pre_tasks: - - name: install dnsmasq - homebrew: name=dnsmasq - - - name: install mkcert - homebrew: name=mkcert - - - name: install nss - homebrew: name=nss - tasks: - - name: net tier - certificate - copy: - dest: "~/Library/Application Support/mkcert/rootCA.pem" - content: | - -----BEGIN CERTIFICATE----- - MIIE9zCCA1+gAwIBAgIQH5gt+MfkJUMRNsUSBjZmhjANBgkqhkiG9w0BAQsFADCB - kzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTQwMgYDVQQLDCtqbWFk - a2luc0BKdXN0aW5zLWlNYWMubG9jYWwgKEp1c3RpbiBBZGtpbnMpMTswOQYDVQQD - DDJta2NlcnQgam1hZGtpbnNASnVzdGlucy1pTWFjLmxvY2FsIChKdXN0aW4gQWRr - aW5zKTAeFw0yMDAzMzAwNjQ2MjNaFw0zMDAzMzAwNjQ2MjNaMIGTMR4wHAYDVQQK - ExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExNDAyBgNVBAsMK2ptYWRraW5zQEp1c3Rp - bnMtaU1hYy5sb2NhbCAoSnVzdGluIEFka2lucykxOzA5BgNVBAMMMm1rY2VydCBq - bWFka2luc0BKdXN0aW5zLWlNYWMubG9jYWwgKEp1c3RpbiBBZGtpbnMpMIIBojAN - BgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA3dzDC+S254Q32Hh+zbVIsWi4RDxN - ELOeypZFjRNbsRMhNo8UBxyV9IfQVHQdYzZxdvCeSDj9afRlzEEUwHHuqEEvy4Ap - P1N7qynpmorkazwaCQq1lAqnq6HK2ofXCCwTJyHDh4ggNST8Dp+YnamI7M089Fy6 - YWMSbywC7SRUc9bSeKbECB8mDCMBanyWopqecXYLUdLsPOn3tXTpiYhmYuVYxpj/ - AsAwIousmjarJ7+FxdouqwkYD/hLwdODzae8XTFeT7i/0is44dam7YKidMgFp1tc - g/XidyXnbCBIxfjacks2T7iRlCnn4xTX7ETfVaHKVcNXhHmxkP7tR8vQ/uchIiRa - /2rGJjpxIqGcOYiequ6G1dkQ81KvZSjgYdO2gaPBAITPSVCSfV7hmsXseLaVuFmO - kjPctqpi56XOjbs25WHToid3cDZXvWH9cW2WYHrJHg+0AS9ZAYzPGQD4cedJw+ld - iOXzSe/SMnSl0KQbGXmoXmkbxLGqDgF7l+FvAgMBAAGjRTBDMA4GA1UdDwEB/wQE - AwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBQZmomUUBGVb3pwnNz/ - LCYDK5dEQTANBgkqhkiG9w0BAQsFAAOCAYEAMuMTWabDrwnidFWCnjWedTMuqwa3 - qxWJwkUJILD4862eDjmmXzz8SBeEJTiemhPheoApJXy/BYlBnmIdnnQoC2Wjg5KC - 2Z4ZlnXAmJr99EjpddYXr1jU0iDTx7OdVHMp53K6675iEqseoccPk1RAhcFav7fV - 3NvWBK/obB1KQWAHaf2e2OLcLqY43zpI8974GOgBRoO2z8Kgyc23Egjzp4ZTFE0U - r8Dp8NlLU8W1NtW+RQeCX8hOjNAT34bkR+25QQHAiSqsyfXMkK05/Z3H4e2KViHL - pCXtScmkueVBAURFJMUBkBZK+25b0oJLqIy2NDVTg7HnEqQGc7n/VuOIqiCX4oOe - 3OFt/pOFtJn05W4vu6SfeFsk9KNlQLNgQGm8ktBj7XUTksCtd1b8wXOzt7DefQC/ - SFhknVIs9pnnygkfq9cwvArL4n1LcTj830gt0/KEdW4CtSpzOT2KW1zXFB100h+Q - uRwm/oeyO6GCrU7t1rklKkKC7yzICO1pnhmK - -----END CERTIFICATE----- - notify: setup mkcert - - - name: net tier - private key - copy: - dest: "~/Library/Application Support/mkcert/rootCA-key.pem" - content: | - -----BEGIN PRIVATE KEY----- - MIIHAAIBADANBgkqhkiG9w0BAQEFAASCBuowggbmAgEAAoIBgQDd3MML5LbnhDfY - eH7NtUixaLhEPE0Qs57KlkWNE1uxEyE2jxQHHJX0h9BUdB1jNnF28J5IOP1p9GXM - QRTAce6oQS/LgCk/U3urKemaiuRrPBoJCrWUCqerocrah9cILBMnIcOHiCA1JPwO - n5idqYjszTz0XLphYxJvLALtJFRz1tJ4psQIHyYMIwFqfJaimp5xdgtR0uw86fe1 - dOmJiGZi5VjGmP8CwDAii6yaNqsnv4XF2i6rCRgP+EvB04PNp7xdMV5PuL/SKzjh - 1qbtgqJ0yAWnW1yD9eJ3JedsIEjF+NpySzZPuJGUKefjFNfsRN9VocpVw1eEebGQ - /u1Hy9D+5yEiJFr/asYmOnEioZw5iJ6q7obV2RDzUq9lKOBh07aBo8EAhM9JUJJ9 - XuGaxex4tpW4WY6SM9y2qmLnpc6NuzblYdOiJ3dwNle9Yf1xbZZgeskeD7QBL1kB - jM8ZAPhx50nD6V2I5fNJ79IydKXQpBsZeaheaRvEsaoOAXuX4W8CAwEAAQKCAYEA - opQ41glXQxavudCq02GKEH91sIMj0h5eOYSfGP9bjMpA53M3sPJwrM2ti4W/V0m5 - Ifi3dKNWiINQ6bmzVEbpJaEHPi//ielKUaaYCejH9BEJ3yBa6U5Zijs4pKUwnUt3 - CZEDcNj/CRK+JpUrSDXJIgZQKZ2d8umfw5nT1yVtQanleAZ01qLExdYNHpSH6kY1 - 310qdF6FQSoOnIk87czngocgZAAPt1tQqrAB3sw65hjCFbeJxUoXuPQxx6qRBm5o - C8qLpgHb2I/jkrZNlZ7hYVn5E+T4PXPzkOFtDYLPh3VpHeldX6ODRD8E44zaw6/9 - ZZ7+SeHDYhoKAJl3MvdxU27a/GihMjp37g3N9//KxfhljHMzrWGdmuIRQkA1kFVD - vbUhXNVM7x/y0sCyz8t852eTlUZqrkjwknEuKSIQPAK5d4m0DiFPxoAAtgPWjab+ - +hcc/sCD7zOPc/KoVWW3LgqnjZFzzCtEf0cD4wqOK5wWKDDjrGdIei46EIK0zh9x - AoHBAOcDmV2+eCAmqCPw96jA+ABWILDfPpDLvojaovFMKa/yBd12K2dsBEzi7UA/ - hLQgSCa982k57m0B4CA9PSkcABMV4xTKCWjklBMAKG2/UOdwQTe8miJLQ5x1LKbD - g2jtWqfT51MPN7gf6On9cpYrsmge8ol/ypudgN3Aq+CHWYQO94b7igLcRIuT39rV - lT+CPn21xjrasrR7dJK71FPFno892RKPy5eW56n2QvwjE7ytHtc0QPBcKWo4FehE - kpFcFwKBwQD128RbHWdk2qaHp3RCfREgH8/rIsVTvL8ex+K3vHxLcykFYQbfRmai - F6oPyTJGCSHloUx2op4HuCWQW+WPzZirH+9nWcQ01TcGP8pUrel8IulUdzdBu/sV - YDRd6muR3HAv4pY68H/84kr3GhTGO7vPpyZAZL0ZXE9Nb1aQexxn/e+O6XxEzN13 - czTaZSZWs9qrqsjT6+97J+cvofUM6rqLsdlBe5fUXmum6Dv27j1pcFurRa017OUK - YSnXbY11RGkCgcEAzEYbdJB7KnrkTTvD0x4nbiy6pYwSh/kR13P1h4dAiYtqckUO - 5lnWh6JWBmzkTF8LTe7DcXW/hfaVmAxuq45N5pKBBR4OKgmNgiuulDULNkvF76I/ - bTm+ZHgcbq4N4leXxTWUpJadP5w/2cC6dV3YWUecUceFggtJK0027sjgd+zAJkUA - 6byahA3TcW9RlSH3XjPBQMOoJ/3Ou/2JKDZkGeenrkkmzzmqSlkvLENcLYer8MIM - 9j2YhYtom8UfEZgrAoHBAK6ttQXTj1ltrDHnfMecmmVLlOsIKlEDYnrZI7DNfzYQ - HQ4QUNSj7VmvHInYthpidK30+yGzCjqL0EyPrjuMpLK4nty8P5YWAuEyw2uEoMYs - +8CibyUKDSuzzaEIY+MfTqoHABviMd0XXpHP+wCZAihYJupLaLszBbkLqOJARf9w - wRq1szAiqhsrRFsC0Ml7QZsEXWmMUPscb7o9BKFnyKBl/Oj0ifw+FZhhmfEodYOL - a+X1PEp7BIRqYlMIKCAwOQKBwQDLV6YUAXOo+Sh9M8J2jTeoErKg7yRoh8aDv9jh - EjsUjaVC5EYhf7a1VQRemDvb+3uI9Bone6+vJHZsnbDoZ2MZ3kU9OOFxTvsoWNWw - M1C/X5nooPQieW2gnKKOZbcx3KnMkD8N5Kxn+vvsUIR9aboj0gsWBprjmkqVtsbL - kQ3pjh5Z1Qm5HzWtwlsCPHOIqB1asjBfiE88yPE89jdglDnz3tNeZTgRq29hB2/F - KP3tqmSdf2gxW2lX2BSDaFAFcW0= - -----END PRIVATE KEY----- - notify: setup mkcert - - - name: net tier - network resovler - become: yes - lineinfile: - state: present - line: nameserver 127.0.0.1 - create: yes - dest: /etc/resolver/mythcoders.test - - - name: net tier - configure dns - become: yes - lineinfile: - state: present - line: address=/mythcoders.test/127.0.0.1 - create: yes - dest: /usr/local/etc/dnsmasq.conf - notify: restart dnsmasq - - - name: net tier - configure dns - become: yes - lineinfile: - state: present - line: no-resolv - create: yes - dest: /usr/local/etc/dnsmasq.conf - notify: restart dnsmasq - - - name: net tier - configure dns - become: yes - lineinfile: - state: present - line: bogus-priv - create: yes - dest: /usr/local/etc/dnsmasq.conf - notify: restart dnsmasq - - - name: net tier - configure dns - become: yes - lineinfile: - state: present - line: domain-needed - create: yes - dest: /usr/local/etc/dnsmasq.conf - notify: restart dnsmasq - - - name: inf tier - docker network - docker_network: - name: "{{ network_name }}" - internal: no diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 311e411..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,47 +0,0 @@ -version: "3.7" - -x-shared-environment-variables: &shared-environment-variables - RAILS_ENV: development - NODE_ENV: development - -services: - app: - image: hermes - build: - context: . - dockerfile: ./Dockerfile.dev - container_name: hermes-app - command: ["./bin/rails", "server", "-b", "0.0.0.0"] - expose: - - "3000" - volumes: - - .:/rails - environment: - <<: *shared-environment-variables - stdin_open: true - tty: true - - # css: - # image: hermes - # container_name: hermes-css - # command: ["sh", "./scripts/css"] - # volumes: - # - .:/rails - # environment: - # <<: *shared-environment-variables - # stdin_open: true - # tty: true - # depends_on: - # - app - - web: - image: nginx:latest - container_name: hermes-web - volumes: - - ./dev/nginx.conf:/etc/nginx/nginx.conf - - ./dev/mythcoders.test.crt:/ssl/mythcoders.test.crt - - ./dev/mythcoders.test.key:/ssl/mythcoders.test.key - - ./log:/var/log/nginx - ports: - - "80:80" - - "443:443" diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake deleted file mode 100644 index 60381ab..0000000 --- a/lib/tasks/auto_annotate_models.rake +++ /dev/null @@ -1,59 +0,0 @@ -# NOTE: only doing this in development as some production environments (Heroku) -# NOTE: are sensitive to local FS writes, and besides -- it's just not proper -# NOTE: to have a dev-mode tool do its thing in production. -if Rails.env.development? - require "annotate" - task :set_annotation_options do - # You can override any of these by setting an environment variable of the - # same name. - Annotate.set_defaults( - "active_admin" => "false", - "additional_file_patterns" => [], - "routes" => "false", - "models" => "true", - "position_in_routes" => "before", - "position_in_class" => "before", - "position_in_test" => "before", - "position_in_fixture" => "before", - "position_in_factory" => "before", - "position_in_serializer" => "before", - "show_foreign_keys" => "true", - "show_complete_foreign_keys" => "false", - "show_indexes" => "true", - "simple_indexes" => "false", - "model_dir" => "app/models", - "root_dir" => "", - "include_version" => "false", - "require" => "", - "exclude_tests" => "false", - "exclude_fixtures" => "false", - "exclude_factories" => "false", - "exclude_serializers" => "false", - "exclude_scaffolds" => "true", - "exclude_controllers" => "true", - "exclude_helpers" => "true", - "exclude_sti_subclasses" => "false", - "ignore_model_sub_dir" => "false", - "ignore_columns" => nil, - "ignore_routes" => nil, - "ignore_unknown_models" => "false", - "hide_limit_column_types" => "integer,bigint,boolean", - "hide_default_column_types" => "json,jsonb,hstore", - "skip_on_db_migrate" => "false", - "format_bare" => "true", - "format_rdoc" => "false", - "format_yard" => "false", - "format_markdown" => "false", - "sort" => "false", - "force" => "false", - "frozen" => "false", - "classified_sort" => "true", - "trace" => "false", - "wrapper_open" => nil, - "wrapper_close" => nil, - "with_comment" => "true" - ) - end - - Annotate.load_tasks -end diff --git a/test/fixtures/backlisted_emails.yml b/test/fixtures/backlisted_emails.yml new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/callbacks.yml b/test/fixtures/callbacks.yml new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/clients.yml b/test/fixtures/clients.yml new file mode 100644 index 0000000..c87cf4a --- /dev/null +++ b/test/fixtures/clients.yml @@ -0,0 +1,5 @@ +one: + name: MyApp + state: active + key: myapp + secret: Internet88 diff --git a/test/fixtures/environments.yml b/test/fixtures/environments.yml new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/messages.yml b/test/fixtures/messages.yml new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/recipients.yml b/test/fixtures/recipients.yml new file mode 100644 index 0000000..e69de29 diff --git a/test/models/backlisted_email_test.rb b/test/models/backlisted_email_test.rb new file mode 100644 index 0000000..304298f --- /dev/null +++ b/test/models/backlisted_email_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class BlacklistedEmailTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/client_test.rb b/test/models/client_test.rb new file mode 100644 index 0000000..9c28491 --- /dev/null +++ b/test/models/client_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +class ClientTest < ActiveSupport::TestCase + test "name is unique" do + client = Client.new(name: clients(:one).name) + refute client.valid? + assert_not_nil client.errors.where(:name, :unique) + end +end diff --git a/test/models/environment_test.rb b/test/models/environment_test.rb new file mode 100644 index 0000000..e77fda6 --- /dev/null +++ b/test/models/environment_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class EnvironmentTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/message_test.rb b/test/models/message_test.rb new file mode 100644 index 0000000..0e0d35b --- /dev/null +++ b/test/models/message_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class MessageTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/recipient_test.rb b/test/models/recipient_test.rb new file mode 100644 index 0000000..2bcf5d6 --- /dev/null +++ b/test/models/recipient_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class RecipientTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end From 0b4bb8c121369ad404bfd6bf014fb401f4a1677a Mon Sep 17 00:00:00 2001 From: Justin Adkins Date: Wed, 11 Sep 2024 22:59:29 -0400 Subject: [PATCH 06/24] Clients and Bans --- .DS_Store | Bin 8196 -> 6148 bytes app/assets/images/.keep | 0 app/assets/images/logo.png | Bin 0 -> 696 bytes app/components/application_component.rb | 3 + app/components/captcha_component.html.erb | 1 + app/components/captcha_component.rb | 11 ++++ .../error_messages_component.html.erb | 6 ++ app/components/error_messages_component.rb | 9 +++ app/controllers/bans_controller.rb | 59 ++++++++++++++++++ app/controllers/clients_controller.rb | 59 ++++++++++++++++++ app/controllers/home_controller.rb | 2 + app/controllers/public_controller.rb | 2 - app/helpers/bans_helper.rb | 2 + app/helpers/clients_helper.rb | 2 + .../controllers/hello_controller.js | 7 --- .../controllers/nested_form_controller.js | 26 ++++++++ app/jobs/ban/log_job.rb | 5 ++ app/models/ban.rb | 22 +++++++ app/models/blacklisted_email.rb | 4 -- app/models/recipient.rb | 2 +- app/views/bans/_ban.html.erb | 12 ++++ app/views/bans/_form.html.erb | 27 ++++++++ app/views/bans/edit.html.erb | 12 ++++ app/views/bans/index.html.erb | 16 +++++ app/views/bans/new.html.erb | 11 ++++ app/views/bans/show.html.erb | 10 +++ app/views/clients/_client.html.erb | 22 +++++++ app/views/clients/_form.html.erb | 37 +++++++++++ app/views/clients/edit.html.erb | 12 ++++ app/views/clients/index.html.erb | 16 +++++ app/views/clients/new.html.erb | 11 ++++ app/views/clients/show.html.erb | 10 +++ app/views/{public => home}/index.html.erb | 0 app/views/layouts/application.html.erb | 46 +++++++++++++- config/environments/production.rb | 2 +- config/importmap.rb | 2 + config/routes.rb | 7 ++- db/migrate/20240115065341_create_messages.rb | 8 +-- ...6_create_solid_queue_tables.solid_queue.rb | 30 ++++----- ...index_to_blocked_executions.solid_queue.rb | 2 +- ...create_recurring_executions.solid_queue.rb | 4 +- ...1309_create_recurring_tasks.solid_queue.rb | 2 +- ...12011311_make_name_not_null.solid_queue.rb | 6 +- db/schema.rb | 10 +-- test/controllers/bans_controller_test.rb | 48 ++++++++++++++ test/controllers/clients_controller_test.rb | 48 ++++++++++++++ test/fixtures/backlisted_emails.yml | 0 test/fixtures/bans.yml | 3 + test/models/backlisted_email_test.rb | 7 --- test/models/ban_test.rb | 19 ++++++ test/system/blacklisted_emails_test.rb | 43 +++++++++++++ test/system/clients_test.rb | 47 ++++++++++++++ vendor/.keep | 0 vendor/javascript/.keep | 0 vendor/javascript/bootstrap.js | 2 + 55 files changed, 696 insertions(+), 58 deletions(-) delete mode 100644 app/assets/images/.keep create mode 100644 app/assets/images/logo.png create mode 100644 app/components/application_component.rb create mode 100644 app/components/captcha_component.html.erb create mode 100644 app/components/captcha_component.rb create mode 100644 app/components/error_messages_component.html.erb create mode 100644 app/components/error_messages_component.rb create mode 100644 app/controllers/bans_controller.rb create mode 100644 app/controllers/clients_controller.rb create mode 100644 app/controllers/home_controller.rb delete mode 100644 app/controllers/public_controller.rb create mode 100644 app/helpers/bans_helper.rb create mode 100644 app/helpers/clients_helper.rb delete mode 100644 app/javascript/controllers/hello_controller.js create mode 100644 app/javascript/controllers/nested_form_controller.js create mode 100644 app/jobs/ban/log_job.rb create mode 100644 app/models/ban.rb delete mode 100644 app/models/blacklisted_email.rb create mode 100644 app/views/bans/_ban.html.erb create mode 100644 app/views/bans/_form.html.erb create mode 100644 app/views/bans/edit.html.erb create mode 100644 app/views/bans/index.html.erb create mode 100644 app/views/bans/new.html.erb create mode 100644 app/views/bans/show.html.erb create mode 100644 app/views/clients/_client.html.erb create mode 100644 app/views/clients/_form.html.erb create mode 100644 app/views/clients/edit.html.erb create mode 100644 app/views/clients/index.html.erb create mode 100644 app/views/clients/new.html.erb create mode 100644 app/views/clients/show.html.erb rename app/views/{public => home}/index.html.erb (100%) create mode 100644 test/controllers/bans_controller_test.rb create mode 100644 test/controllers/clients_controller_test.rb delete mode 100644 test/fixtures/backlisted_emails.yml create mode 100644 test/fixtures/bans.yml delete mode 100644 test/models/backlisted_email_test.rb create mode 100644 test/models/ban_test.rb create mode 100644 test/system/blacklisted_emails_test.rb create mode 100644 test/system/clients_test.rb delete mode 100644 vendor/.keep delete mode 100644 vendor/javascript/.keep create mode 100644 vendor/javascript/bootstrap.js diff --git a/.DS_Store b/.DS_Store index 38075d0b94068c7a36b6b99f8935c7cb37fdebe2..581ec27d4cf7b3642ce66af7a35586b456e92bb1 100644 GIT binary patch delta 420 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{Mvv5r;6q~50D9Q|y2ZL^qj8dzHDD43g>*Vb}!h$`z_ z2gPUS8R(ncoF52&efV``HEG|}&(gH0|pn$k^i!HYl*+MT|*4>?fPMFS=o!Ko& zh*i)hG@5ACM2SXy6mQW7qDB)Rh#DRYF`|hNVtmmDAB+$Bfd82@3$%rV_+T*1N#^`> z{{MV4=X~e;XZFl8#?VnTS{bWjjHz@8%d4rnK@o9rOe#v~sU!=+Gd9GEESDSgMsoI~ z-jO3>AYve5AYve5AY$NlV1VA)qNq1{@5^XZM+`&^+>s23=R<-HVUwX9lQwvCP!((e z$cimMQ0ScY0Rbiv+GJ?Qqz#~SO}TqO2t~NXfP_;#A-a=IhIUL^31^UShVae^cPI$% zPPjzSogpc0R7VU%3`}M~q)!!F#tt!y`Pc8?-5f>EZ<+e zA$K(GXZ@nrkuB^MtzOr)bLI1FZjWV-W_WGNb^NU5n1ujf876hv*Jn9~JKEtE9m5N- zX&H!7$?*E)$5*tswKXT&TiZ`GCyuwawybSVtZrL#;zUfH)3AK~uFPS3*l|zGsUUnD zu;~+~_Vna=*dW)`E}WMd)2j8p{sAq+XO(F1JtMy5I^G_$;E~PnnI27Y zOWt*M7EBTE%e!`Q*zq#FCZDzQMLX-8n`}F6J!*RWzIoIaXM>(w@KZs@ev7cem*KqV znY&B^SS7QQU|#Knp(A#7+MM`3i<(;6);-v{Wyix8r_Y$lHEninU&->UoNW$dy}aod zmUC$LsAc#=gT$cYTL&$(5R28|?_MW6Y+jr@ua4{W`us9V_PvHxd4t+t%vnc@mVZp% zLr*M>sr8$+fMoB>4@U4{TIv^v(TwcX*iQ<4L#Pky2Iu#Q|~e?OD(7 z88Mx!qw4CW*!e+kC|fXlMoDQQrfa*Z2CGJX0orU>zFUx#B=nuCIv_5$$uQ_jd|ut$ zU1?pXrLmlnMY^UXm-6P{sH)nKTq0K}ptT{{B3m(fW9gJRN!HEwF_Vq3W9&40m7QU4 zvya%P>^!@`F0t>~59~*Fnf=E8V1J>V#YrIXqdo(GgS^gU1HjdJ8hc@uxAtNZrI zn@iI~rqs-uT{~w%!{VhYR9S19FVb6LDa;}w)pu>iX= z-lTD;vav>M*LWqRmTYd&Hfo%SY?tj#@l>3PMEMtjeUF`EpOIiMl3;&fzp~%i6%y$T z)R90JVKExfjHM*fwP?qBY`|u8p&MICvc1@YJ`7+Gd6*>FAy_EDM-e4FhQ~>^r|=|+ z_E|iK=kWs0;5EFCH}Ga4-w*Kd1UYUUFGqYbS&pT2!LeQE5Jk!&9uJCIx5z++>{loD z|C?|A{r?uP7Iljlh#2@kGJwj?bY};R{ASNng<=Uh9-%`N(Qi!J078}MBK*O2ob1&< l4Cy=(#*(2Ola?Y>{__t3!7uvg{eS%r*695oNb!!U{sFtFD@yEk z|NjgPK!N`t0!V>~hM*L)P$11%666=m;PC858i^mS!_#3msw zXz=ik%?6-!yQhm|h{fsL%Nw%}8wju^{N`Pi(DXv>ChK}$lj;_!UE3Z6?YVaC!N!u4 z&!+Iq^j7eHknm@Ut*3hQs@e%p|9^VkqU=6Vc9Fe7d7#0^yIn3V%QJs@{F!q^=V43! zk=YMg^|h6@*ra4KKIUw3o7bJoYxLGr#cN^7)6%B(fhCJG+;{xzTl74+4S}TF3=0|jFK9%wBuWK6WB9s7#dFDy9|6<8#jJLD^km24*XlQ{ zf823eTw?#Uc~$p0oz6-I^Q9jm3bPXW1I)axZriwV!||uhLB1CX3W9wv>mJ-4bU2~m zj5J#Z4+EF^Wd)<0HB)mPoH(ycMDg>( znp=Wdd`}P9tdZI0|F5}j-_CQ4RmJ%`FC1ueS@v0gh2t5+T6TpQ!nbaRH>A&8V{}gS zS<5y)7d1wS!i2m-GqWEiv1xE8wE8<7|L%60CHP&-*&-3M^J_P>-r@|Y5ikG% literal 0 HcmV?d00001 diff --git a/app/components/application_component.rb b/app/components/application_component.rb new file mode 100644 index 0000000..5235b09 --- /dev/null +++ b/app/components/application_component.rb @@ -0,0 +1,3 @@ +class ApplicationComponent < ViewComponent::Base + include ViewComponent::Translatable +end diff --git a/app/components/captcha_component.html.erb b/app/components/captcha_component.html.erb new file mode 100644 index 0000000..802a838 --- /dev/null +++ b/app/components/captcha_component.html.erb @@ -0,0 +1 @@ +
diff --git a/app/components/captcha_component.rb b/app/components/captcha_component.rb new file mode 100644 index 0000000..4d46509 --- /dev/null +++ b/app/components/captcha_component.rb @@ -0,0 +1,11 @@ +class CaptchaComponent < ApplicationComponent + def initialize(css_class: "", theme: "light") + @css_classes = "h-captcha #{css_class}".strip + @theme = theme + @site_key = Rails.application.credentials.dig(:hcaptcha, :site_key) + end + + def render? + !Rails.env.test? + end +end diff --git a/app/components/error_messages_component.html.erb b/app/components/error_messages_component.html.erb new file mode 100644 index 0000000..b06679d --- /dev/null +++ b/app/components/error_messages_component.html.erb @@ -0,0 +1,6 @@ +There were some errors with your submission +
    + <% @errors.each do |error| %> +
  • <%= error %>
  • + <% end %> +
diff --git a/app/components/error_messages_component.rb b/app/components/error_messages_component.rb new file mode 100644 index 0000000..7990211 --- /dev/null +++ b/app/components/error_messages_component.rb @@ -0,0 +1,9 @@ +class ErrorMessagesComponent < ApplicationComponent + def initialize(*models) + @errors = models.map { |o| o.errors.full_messages }.flatten + end + + def render? + @errors.any? + end +end diff --git a/app/controllers/bans_controller.rb b/app/controllers/bans_controller.rb new file mode 100644 index 0000000..7e3ac64 --- /dev/null +++ b/app/controllers/bans_controller.rb @@ -0,0 +1,59 @@ +class BansController < ApplicationController + before_action :set_ban, only: %i[show edit update destroy] + + # GET /bans + def index + @bans = Ban.all + end + + # GET /bans/1 + def show + end + + # GET /bans/new + def new + @ban = Ban.new + end + + # GET /bans/1/edit + def edit + end + + # POST /bans + def create + @ban = Ban.new(ban_params) + + if @ban.save + redirect_to @ban, notice: "Ban was successfully created." + else + render :new, status: :unprocessable_entity + end + end + + # PATCH/PUT /bans/1 + def update + if @ban.update(ban_params) + redirect_to @ban, notice: "Ban was successfully updated.", status: :see_other + else + render :edit, status: :unprocessable_entity + end + end + + # DELETE /bans/1 + def destroy + @ban.destroy! + redirect_to bans_url, notice: "Ban was successfully destroyed.", status: :see_other + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_ban + @ban = Ban.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def ban_params + params.require(:ban).permit(:address, :reason) + end +end diff --git a/app/controllers/clients_controller.rb b/app/controllers/clients_controller.rb new file mode 100644 index 0000000..d2a0368 --- /dev/null +++ b/app/controllers/clients_controller.rb @@ -0,0 +1,59 @@ +class ClientsController < ApplicationController + before_action :set_client, only: %i[show edit update destroy] + + # GET /clients + def index + @clients = Client.all + end + + # GET /clients/1 + def show + end + + # GET /clients/new + def new + @client = Client.new + end + + # GET /clients/1/edit + def edit + end + + # POST /clients + def create + @client = Client.new(client_params) + + if @client.save + redirect_to @client, notice: "Client was successfully created." + else + render :new, status: :unprocessable_entity + end + end + + # PATCH/PUT /clients/1 + def update + if @client.update(client_params) + redirect_to @client, notice: "Client was successfully updated.", status: :see_other + else + render :edit, status: :unprocessable_entity + end + end + + # DELETE /clients/1 + def destroy + @client.destroy! + redirect_to clients_url, notice: "Client was successfully destroyed.", status: :see_other + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_client + @client = Client.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def client_params + params.require(:client).permit(:name, :state, :key, :secret) + end +end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb new file mode 100644 index 0000000..fc0b474 --- /dev/null +++ b/app/controllers/home_controller.rb @@ -0,0 +1,2 @@ +class HomeController < ApplicationController +end diff --git a/app/controllers/public_controller.rb b/app/controllers/public_controller.rb deleted file mode 100644 index 2857026..0000000 --- a/app/controllers/public_controller.rb +++ /dev/null @@ -1,2 +0,0 @@ -class PublicController < ApplicationController -end diff --git a/app/helpers/bans_helper.rb b/app/helpers/bans_helper.rb new file mode 100644 index 0000000..f867b03 --- /dev/null +++ b/app/helpers/bans_helper.rb @@ -0,0 +1,2 @@ +module BansHelper +end diff --git a/app/helpers/clients_helper.rb b/app/helpers/clients_helper.rb new file mode 100644 index 0000000..9015906 --- /dev/null +++ b/app/helpers/clients_helper.rb @@ -0,0 +1,2 @@ +module ClientsHelper +end diff --git a/app/javascript/controllers/hello_controller.js b/app/javascript/controllers/hello_controller.js deleted file mode 100644 index 5975c07..0000000 --- a/app/javascript/controllers/hello_controller.js +++ /dev/null @@ -1,7 +0,0 @@ -import { Controller } from "@hotwired/stimulus" - -export default class extends Controller { - connect() { - this.element.textContent = "Hello World!" - } -} diff --git a/app/javascript/controllers/nested_form_controller.js b/app/javascript/controllers/nested_form_controller.js new file mode 100644 index 0000000..f34422f --- /dev/null +++ b/app/javascript/controllers/nested_form_controller.js @@ -0,0 +1,26 @@ +import { Controller } from "@hotwired/stimulus" + +export default class extends Controller { + static targets = ["template", "container"] + + add_association(event) { + event.preventDefault() + + var content = this.templateTarget.innerHTML.replace(/NEW_RECORD/g, new Date().getTime()) + this.containerTarget.insertAdjacentHTML('beforeend', content) + } + + remove_association(event) { + event.preventDefault() + + if (confirm('Are you sure you want to delete this record?')) { + let wrapper = event.target.closest("tr") + if (wrapper.dataset.newRecord == "true") { + wrapper.remove() + } else { + wrapper.querySelector("input[name*='_destroy']").value = 1 + wrapper.style.display = "none" + } + } + } +} diff --git a/app/jobs/ban/log_job.rb b/app/jobs/ban/log_job.rb new file mode 100644 index 0000000..508165d --- /dev/null +++ b/app/jobs/ban/log_job.rb @@ -0,0 +1,5 @@ +class Ban::LogJob < ApplicationJob + def perform(email, reason) + Ban.log_now(email, reason) + end +end diff --git a/app/models/ban.rb b/app/models/ban.rb new file mode 100644 index 0000000..d83630d --- /dev/null +++ b/app/models/ban.rb @@ -0,0 +1,22 @@ +class Ban < ApplicationRecord + normalizes :address, with: -> { _1.downcase } + + validates :address, presence: true, uniqueness: true + validates :reason, presence: true + + def self.registered?(email) + where(address: email).any? + end + + def self.log_now(email, reason) + ban = find_or_initialize_by(address: email) + return true if ban.persisted? + + ban.reason = reason + ban.save! + end + + def self.log_later(email, reason) + Ban::LogJob.perform_later(email, reason) + end +end diff --git a/app/models/blacklisted_email.rb b/app/models/blacklisted_email.rb deleted file mode 100644 index a451a55..0000000 --- a/app/models/blacklisted_email.rb +++ /dev/null @@ -1,4 +0,0 @@ -class BlacklistedEmail < ApplicationRecord - validates :address, presence: true, uniqueness: true - validates :reason, presence: true -end diff --git a/app/models/recipient.rb b/app/models/recipient.rb index a2ff7d0..87a96cb 100644 --- a/app/models/recipient.rb +++ b/app/models/recipient.rb @@ -1,3 +1,3 @@ class Recipient < ApplicationRecord - encrypts :email_address, deterministic: true + encrypts :address, deterministic: true end diff --git a/app/views/bans/_ban.html.erb b/app/views/bans/_ban.html.erb new file mode 100644 index 0000000..42f8606 --- /dev/null +++ b/app/views/bans/_ban.html.erb @@ -0,0 +1,12 @@ +
+

+ Address: + <%= ban.address %> +

+ +

+ Reason: + <%= ban.reason %> +

+ +
diff --git a/app/views/bans/_form.html.erb b/app/views/bans/_form.html.erb new file mode 100644 index 0000000..4c2d601 --- /dev/null +++ b/app/views/bans/_form.html.erb @@ -0,0 +1,27 @@ +<%= form_with(model: ban) do |form| %> + <% if ban.errors.any? %> +
+

<%= pluralize(ban.errors.count, "error") %> prohibited this ban from being saved:

+ +
    + <% ban.errors.each do |error| %> +
  • <%= error.full_message %>
  • + <% end %> +
+
+ <% end %> + +
+ <%= form.label :address, style: "display: block" %> + <%= form.text_field :address %> +
+ +
+ <%= form.label :reason, style: "display: block" %> + <%= form.text_field :reason %> +
+ +
+ <%= form.submit %> +
+<% end %> diff --git a/app/views/bans/edit.html.erb b/app/views/bans/edit.html.erb new file mode 100644 index 0000000..73dbc39 --- /dev/null +++ b/app/views/bans/edit.html.erb @@ -0,0 +1,12 @@ +<% content_for :title, "Editing ban" %> + +

Editing ban

+ +<%= render "form", ban: @ban %> + +
+ +
+ <%= link_to "Show this ban", @ban %> | + <%= link_to "Back to bans", bans_path %> +
diff --git a/app/views/bans/index.html.erb b/app/views/bans/index.html.erb new file mode 100644 index 0000000..bf7c19d --- /dev/null +++ b/app/views/bans/index.html.erb @@ -0,0 +1,16 @@ +

<%= notice %>

+ +<% content_for :title, "Bans" %> + +

Bans

+ +
+ <% @bans.each do |ban| %> + <%= render ban %> +

+ <%= link_to "Show this ban", ban %> +

+ <% end %> +
+ +<%= link_to "New ban", new_ban_path %> diff --git a/app/views/bans/new.html.erb b/app/views/bans/new.html.erb new file mode 100644 index 0000000..eba2167 --- /dev/null +++ b/app/views/bans/new.html.erb @@ -0,0 +1,11 @@ +<% content_for :title, "New ban" %> + +

New ban

+ +<%= render "form", ban: @ban %> + +
+ +
+ <%= link_to "Back to bans", bans_path %> +
diff --git a/app/views/bans/show.html.erb b/app/views/bans/show.html.erb new file mode 100644 index 0000000..406564e --- /dev/null +++ b/app/views/bans/show.html.erb @@ -0,0 +1,10 @@ +

<%= notice %>

+ +<%= render @ban %> + +
+ <%= link_to "Edit this ban", edit_ban_path(@ban) %> | + <%= link_to "Back to bans", bans_path %> + + <%= button_to "Destroy this ban", @ban, method: :delete %> +
diff --git a/app/views/clients/_client.html.erb b/app/views/clients/_client.html.erb new file mode 100644 index 0000000..57140ef --- /dev/null +++ b/app/views/clients/_client.html.erb @@ -0,0 +1,22 @@ +
+

+ Name: + <%= client.name %> +

+ +

+ State: + <%= client.state %> +

+ +

+ Key: + <%= client.key %> +

+ +

+ Secret: + <%= client.secret %> +

+ +
diff --git a/app/views/clients/_form.html.erb b/app/views/clients/_form.html.erb new file mode 100644 index 0000000..2631a89 --- /dev/null +++ b/app/views/clients/_form.html.erb @@ -0,0 +1,37 @@ +<%= form_with(model: client) do |form| %> + <% if client.errors.any? %> +
+

<%= pluralize(client.errors.count, "error") %> prohibited this client from being saved:

+ +
    + <% client.errors.each do |error| %> +
  • <%= error.full_message %>
  • + <% end %> +
+
+ <% end %> + +
+ <%= form.label :name, style: "display: block" %> + <%= form.text_field :name %> +
+ +
+ <%= form.label :state, style: "display: block" %> + <%= form.text_field :state %> +
+ +
+ <%= form.label :key, style: "display: block" %> + <%= form.text_field :key %> +
+ +
+ <%= form.label :secret, style: "display: block" %> + <%= form.text_field :secret %> +
+ +
+ <%= form.submit %> +
+<% end %> diff --git a/app/views/clients/edit.html.erb b/app/views/clients/edit.html.erb new file mode 100644 index 0000000..7110143 --- /dev/null +++ b/app/views/clients/edit.html.erb @@ -0,0 +1,12 @@ +<% content_for :title, "Editing client" %> + +

Editing client

+ +<%= render "form", client: @client %> + +
+ +
+ <%= link_to "Show this client", @client %> | + <%= link_to "Back to clients", clients_path %> +
diff --git a/app/views/clients/index.html.erb b/app/views/clients/index.html.erb new file mode 100644 index 0000000..870fc74 --- /dev/null +++ b/app/views/clients/index.html.erb @@ -0,0 +1,16 @@ +

<%= notice %>

+ +<% content_for :title, "Clients" %> + +

Clients

+ +
+ <% @clients.each do |client| %> + <%= render client %> +

+ <%= link_to "Show this client", client %> +

+ <% end %> +
+ +<%= link_to "New client", new_client_path %> diff --git a/app/views/clients/new.html.erb b/app/views/clients/new.html.erb new file mode 100644 index 0000000..9f460cb --- /dev/null +++ b/app/views/clients/new.html.erb @@ -0,0 +1,11 @@ +<% content_for :title, "New client" %> + +

New client

+ +<%= render "form", client: @client %> + +
+ +
+ <%= link_to "Back to clients", clients_path %> +
diff --git a/app/views/clients/show.html.erb b/app/views/clients/show.html.erb new file mode 100644 index 0000000..20794cf --- /dev/null +++ b/app/views/clients/show.html.erb @@ -0,0 +1,10 @@ +

<%= notice %>

+ +<%= render @client %> + +
+ <%= link_to "Edit this client", edit_client_path(@client) %> | + <%= link_to "Back to clients", clients_path %> + + <%= button_to "Destroy this client", @client, method: :delete %> +
diff --git a/app/views/public/index.html.erb b/app/views/home/index.html.erb similarity index 100% rename from app/views/public/index.html.erb rename to app/views/home/index.html.erb diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index d0dc47d..c007097 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,16 +1,58 @@ - + Hermes <%= csrf_meta_tags %> <%= csp_meta_tag %> + <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%= javascript_importmap_tags %> - <%= yield %> + + +
+ <%= yield %> +
diff --git a/config/environments/production.rb b/config/environments/production.rb index 54977a3..269b507 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -46,7 +46,7 @@ config.force_ssl = true # Log to STDOUT by default - config.logger = ActiveSupport::Logger.new(STDOUT) + config.logger = ActiveSupport::Logger.new($stdout) .tap { |logger| logger.formatter = ::Logger::Formatter.new } .then { |logger| ActiveSupport::TaggedLogging.new(logger) } diff --git a/config/importmap.rb b/config/importmap.rb index bc060ed..8e1824a 100644 --- a/config/importmap.rb +++ b/config/importmap.rb @@ -5,3 +5,5 @@ pin "@hotwired/stimulus", to: "stimulus.min.js" pin "@hotwired/stimulus-loading", to: "stimulus-loading.js" pin_all_from "app/javascript/controllers", under: "controllers" + +pin "bootstrap" # @5.3.3 diff --git a/config/routes.rb b/config/routes.rb index b3d65d5..983770e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,8 @@ Rails.application.routes.draw do + root "home#index" get "up" => "rails/health#show", :as => :rails_health_check - - root "public#index" - mount MissionControl::Jobs::Engine, at: "/jobs" + + resources :clients + resources :bans end diff --git a/db/migrate/20240115065341_create_messages.rb b/db/migrate/20240115065341_create_messages.rb index e478abd..647a1af 100644 --- a/db/migrate/20240115065341_create_messages.rb +++ b/db/migrate/20240115065341_create_messages.rb @@ -9,13 +9,13 @@ def change create_table :messages do |t| t.references :client, null: false, foreign_key: true t.string :uuid, null: false, index: {unique: true} - t.string :sender + t.string :environment + t.string :from t.string :subject t.string :html_body t.string :text_body t.string :content_type t.string :priority - t.string :environment t.datetime :scheduled_at t.timestamps end @@ -24,7 +24,7 @@ def change t.references :message, null: false, foreign_key: true t.string :uuid, null: false, index: {unique: true} t.string :recipient_type - t.string :email_address, null: false + t.string :address, null: false t.datetime :sent_at t.datetime :delivered_at t.datetime :opened_at @@ -32,7 +32,7 @@ def change t.timestamps end - create_table :blacklisted_emails do |t| + create_table :bans do |t| t.string :address, null: false, index: {unique: true} t.string :reason, null: false t.timestamps diff --git a/db/queue_migrate/20240912011306_create_solid_queue_tables.solid_queue.rb b/db/queue_migrate/20240912011306_create_solid_queue_tables.solid_queue.rb index 6d8c4f6..2591b73 100644 --- a/db/queue_migrate/20240912011306_create_solid_queue_tables.solid_queue.rb +++ b/db/queue_migrate/20240912011306_create_solid_queue_tables.solid_queue.rb @@ -13,42 +13,42 @@ def change t.timestamps - t.index [ :queue_name, :finished_at ], name: "index_solid_queue_jobs_for_filtering" - t.index [ :scheduled_at, :finished_at ], name: "index_solid_queue_jobs_for_alerting" + t.index [:queue_name, :finished_at], name: "index_solid_queue_jobs_for_filtering" + t.index [:scheduled_at, :finished_at], name: "index_solid_queue_jobs_for_alerting" end create_table :solid_queue_scheduled_executions do |t| - t.references :job, index: { unique: true }, null: false + t.references :job, index: {unique: true}, null: false t.string :queue_name, null: false t.integer :priority, default: 0, null: false t.datetime :scheduled_at, null: false t.datetime :created_at, null: false - t.index [ :scheduled_at, :priority, :job_id ], name: "index_solid_queue_dispatch_all" + t.index [:scheduled_at, :priority, :job_id], name: "index_solid_queue_dispatch_all" end create_table :solid_queue_ready_executions do |t| - t.references :job, index: { unique: true }, null: false + t.references :job, index: {unique: true}, null: false t.string :queue_name, null: false t.integer :priority, default: 0, null: false t.datetime :created_at, null: false - t.index [ :priority, :job_id ], name: "index_solid_queue_poll_all" - t.index [ :queue_name, :priority, :job_id ], name: "index_solid_queue_poll_by_queue" + t.index [:priority, :job_id], name: "index_solid_queue_poll_all" + t.index [:queue_name, :priority, :job_id], name: "index_solid_queue_poll_by_queue" end create_table :solid_queue_claimed_executions do |t| - t.references :job, index: { unique: true }, null: false + t.references :job, index: {unique: true}, null: false t.bigint :process_id t.datetime :created_at, null: false - t.index [ :process_id, :job_id ] + t.index [:process_id, :job_id] end create_table :solid_queue_blocked_executions do |t| - t.references :job, index: { unique: true }, null: false + t.references :job, index: {unique: true}, null: false t.string :queue_name, null: false t.integer :priority, default: 0, null: false t.string :concurrency_key, null: false @@ -56,17 +56,17 @@ def change t.datetime :created_at, null: false - t.index [ :expires_at, :concurrency_key ], name: "index_solid_queue_blocked_executions_for_maintenance" + t.index [:expires_at, :concurrency_key], name: "index_solid_queue_blocked_executions_for_maintenance" end create_table :solid_queue_failed_executions do |t| - t.references :job, index: { unique: true }, null: false + t.references :job, index: {unique: true}, null: false t.text :error t.datetime :created_at, null: false end create_table :solid_queue_pauses do |t| - t.string :queue_name, null: false, index: { unique: true } + t.string :queue_name, null: false, index: {unique: true} t.datetime :created_at, null: false end @@ -83,13 +83,13 @@ def change end create_table :solid_queue_semaphores do |t| - t.string :key, null: false, index: { unique: true } + t.string :key, null: false, index: {unique: true} t.integer :value, default: 1, null: false t.datetime :expires_at, null: false, index: true t.timestamps - t.index [ :key, :value ], name: "index_solid_queue_semaphores_on_key_and_value" + t.index [:key, :value], name: "index_solid_queue_semaphores_on_key_and_value" end add_foreign_key :solid_queue_blocked_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade diff --git a/db/queue_migrate/20240912011307_add_missing_index_to_blocked_executions.solid_queue.rb b/db/queue_migrate/20240912011307_add_missing_index_to_blocked_executions.solid_queue.rb index 2d96b10..53e74dc 100644 --- a/db/queue_migrate/20240912011307_add_missing_index_to_blocked_executions.solid_queue.rb +++ b/db/queue_migrate/20240912011307_add_missing_index_to_blocked_executions.solid_queue.rb @@ -1,6 +1,6 @@ # This migration comes from solid_queue (originally 20240110143450) class AddMissingIndexToBlockedExecutions < ActiveRecord::Migration[7.1] def change - add_index :solid_queue_blocked_executions, [ :concurrency_key, :priority, :job_id ], name: "index_solid_queue_blocked_executions_for_release" + add_index :solid_queue_blocked_executions, [:concurrency_key, :priority, :job_id], name: "index_solid_queue_blocked_executions_for_release" end end diff --git a/db/queue_migrate/20240912011308_create_recurring_executions.solid_queue.rb b/db/queue_migrate/20240912011308_create_recurring_executions.solid_queue.rb index 4c49821..7f441b2 100644 --- a/db/queue_migrate/20240912011308_create_recurring_executions.solid_queue.rb +++ b/db/queue_migrate/20240912011308_create_recurring_executions.solid_queue.rb @@ -2,12 +2,12 @@ class CreateRecurringExecutions < ActiveRecord::Migration[7.1] def change create_table :solid_queue_recurring_executions do |t| - t.references :job, index: { unique: true }, null: false + t.references :job, index: {unique: true}, null: false t.string :task_key, null: false t.datetime :run_at, null: false t.datetime :created_at, null: false - t.index [ :task_key, :run_at ], unique: true + t.index [:task_key, :run_at], unique: true end add_foreign_key :solid_queue_recurring_executions, :solid_queue_jobs, column: :job_id, on_delete: :cascade diff --git a/db/queue_migrate/20240912011309_create_recurring_tasks.solid_queue.rb b/db/queue_migrate/20240912011309_create_recurring_tasks.solid_queue.rb index 507c9e7..020c7b0 100644 --- a/db/queue_migrate/20240912011309_create_recurring_tasks.solid_queue.rb +++ b/db/queue_migrate/20240912011309_create_recurring_tasks.solid_queue.rb @@ -2,7 +2,7 @@ class CreateRecurringTasks < ActiveRecord::Migration[7.1] def change create_table :solid_queue_recurring_tasks do |t| - t.string :key, null: false, index: { unique: true } + t.string :key, null: false, index: {unique: true} t.string :schedule, null: false t.string :command, limit: 2048 t.string :class_name diff --git a/db/queue_migrate/20240912011311_make_name_not_null.solid_queue.rb b/db/queue_migrate/20240912011311_make_name_not_null.solid_queue.rb index f56dd4d..7678735 100644 --- a/db/queue_migrate/20240912011311_make_name_not_null.solid_queue.rb +++ b/db/queue_migrate/20240912011311_make_name_not_null.solid_queue.rb @@ -2,16 +2,16 @@ class MakeNameNotNull < ActiveRecord::Migration[7.1] def up SolidQueue::Process.where(name: nil).find_each do |process| - process.name ||= [ process.kind.downcase, SecureRandom.hex(10) ].join("-") + process.name ||= [process.kind.downcase, SecureRandom.hex(10)].join("-") process.save! end change_column :solid_queue_processes, :name, :string, null: false - add_index :solid_queue_processes, [ :name, :supervisor_id ], unique: true + add_index :solid_queue_processes, [:name, :supervisor_id], unique: true end def down - remove_index :solid_queue_processes, [ :name, :supervisor_id ] + remove_index :solid_queue_processes, [:name, :supervisor_id] change_column :solid_queue_processes, :name, :string, null: true end end diff --git a/db/schema.rb b/db/schema.rb index 9606682..a935bc0 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,12 +11,12 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[7.2].define(version: 2024_01_15_065341) do - create_table "blacklisted_emails", force: :cascade do |t| + create_table "bans", force: :cascade do |t| t.string "address", null: false t.string "reason", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.index ["address"], name: "index_blacklisted_emails_on_address", unique: true + t.index ["address"], name: "index_bans_on_address", unique: true end create_table "callbacks", force: :cascade do |t| @@ -54,13 +54,13 @@ create_table "messages", force: :cascade do |t| t.integer "client_id", null: false t.string "uuid", null: false - t.string "sender" + t.string "environment" + t.string "from" t.string "subject" t.string "html_body" t.string "text_body" t.string "content_type" t.string "priority" - t.string "environment" t.datetime "scheduled_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -72,7 +72,7 @@ t.integer "message_id", null: false t.string "uuid", null: false t.string "recipient_type" - t.string "email_address", null: false + t.string "address", null: false t.datetime "sent_at" t.datetime "delivered_at" t.datetime "opened_at" diff --git a/test/controllers/bans_controller_test.rb b/test/controllers/bans_controller_test.rb new file mode 100644 index 0000000..e97d3dd --- /dev/null +++ b/test/controllers/bans_controller_test.rb @@ -0,0 +1,48 @@ +require "test_helper" + +class BansControllerTest < ActionDispatch::IntegrationTest + setup do + @ban = bans(:one) + end + + test "should get index" do + get bans_url + assert_response :success + end + + test "should get new" do + get new_ban_url + assert_response :success + end + + test "should create ban" do + assert_difference("Ban.count") do + post bans_url, params: {ban: {address: @ban.address, reason: @ban.reason}} + end + + assert_redirected_to ban_url(Ban.last) + end + + test "should show ban" do + get ban_url(@ban) + assert_response :success + end + + test "should get edit" do + get edit_ban_url(@ban) + assert_response :success + end + + test "should update ban" do + patch ban_url(@ban), params: {ban: {address: @ban.address, reason: @ban.reason}} + assert_redirected_to ban_url(@ban) + end + + test "should destroy ban" do + assert_difference("Ban.count", -1) do + delete ban_url(@ban) + end + + assert_redirected_to bans_url + end +end diff --git a/test/controllers/clients_controller_test.rb b/test/controllers/clients_controller_test.rb new file mode 100644 index 0000000..01c53c7 --- /dev/null +++ b/test/controllers/clients_controller_test.rb @@ -0,0 +1,48 @@ +require "test_helper" + +class ClientsControllerTest < ActionDispatch::IntegrationTest + setup do + @client = clients(:one) + end + + test "should get index" do + get clients_url + assert_response :success + end + + test "should get new" do + get new_client_url + assert_response :success + end + + test "should create client" do + assert_difference("Client.count") do + post clients_url, params: {client: {key: @client.key, name: @client.name, secret: @client.secret, state: @client.state}} + end + + assert_redirected_to client_url(Client.last) + end + + test "should show client" do + get client_url(@client) + assert_response :success + end + + test "should get edit" do + get edit_client_url(@client) + assert_response :success + end + + test "should update client" do + patch client_url(@client), params: {client: {key: @client.key, name: @client.name, secret: @client.secret, state: @client.state}} + assert_redirected_to client_url(@client) + end + + test "should destroy client" do + assert_difference("Client.count", -1) do + delete client_url(@client) + end + + assert_redirected_to clients_url + end +end diff --git a/test/fixtures/backlisted_emails.yml b/test/fixtures/backlisted_emails.yml deleted file mode 100644 index e69de29..0000000 diff --git a/test/fixtures/bans.yml b/test/fixtures/bans.yml new file mode 100644 index 0000000..01f57ae --- /dev/null +++ b/test/fixtures/bans.yml @@ -0,0 +1,3 @@ +one: + address: me@you.com + reason: spam diff --git a/test/models/backlisted_email_test.rb b/test/models/backlisted_email_test.rb deleted file mode 100644 index 304298f..0000000 --- a/test/models/backlisted_email_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "test_helper" - -class BlacklistedEmailTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end -end diff --git a/test/models/ban_test.rb b/test/models/ban_test.rb new file mode 100644 index 0000000..6a0ba54 --- /dev/null +++ b/test/models/ban_test.rb @@ -0,0 +1,19 @@ +require "test_helper" + +class BanTest < ActiveSupport::TestCase + test "registered?" do + refute Ban.registered?("test@you.com") + Ban.register "test@you.com", "spam" + assert Ban.registered?("test@you.com") + end + + test "register" do + assert_difference "Ban.count" do + Ban.register "test@you.com", "spam" + end + + assert_no_difference "Ban.count" do + Ban.register "test@you.com", "spam" + end + end +end diff --git a/test/system/blacklisted_emails_test.rb b/test/system/blacklisted_emails_test.rb new file mode 100644 index 0000000..9120abc --- /dev/null +++ b/test/system/blacklisted_emails_test.rb @@ -0,0 +1,43 @@ +require "application_system_test_case" + +class BansTest < ApplicationSystemTestCase + setup do + @ban = bans(:one) + end + + test "visiting the index" do + visit bans_url + assert_selector "h1", text: "Blacklisted emails" + end + + test "should create ban" do + visit bans_url + click_on "New ban" + + fill_in "Address", with: @ban.address + fill_in "Reason", with: @ban.reason + click_on "Create Ban" + + assert_text "Ban was successfully created" + click_on "Back" + end + + test "should update Ban" do + visit ban_url(@ban) + click_on "Edit this ban", match: :first + + fill_in "Address", with: @ban.address + fill_in "Reason", with: @ban.reason + click_on "Update Ban" + + assert_text "Ban was successfully updated" + click_on "Back" + end + + test "should destroy Ban" do + visit ban_url(@ban) + click_on "Destroy this ban", match: :first + + assert_text "Ban was successfully destroyed" + end +end diff --git a/test/system/clients_test.rb b/test/system/clients_test.rb new file mode 100644 index 0000000..ed530ef --- /dev/null +++ b/test/system/clients_test.rb @@ -0,0 +1,47 @@ +require "application_system_test_case" + +class ClientsTest < ApplicationSystemTestCase + setup do + @client = clients(:one) + end + + test "visiting the index" do + visit clients_url + assert_selector "h1", text: "Clients" + end + + test "should create client" do + visit clients_url + click_on "New client" + + fill_in "Key", with: @client.key + fill_in "Name", with: @client.name + fill_in "Secret", with: @client.secret + fill_in "State", with: @client.state + click_on "Create Client" + + assert_text "Client was successfully created" + click_on "Back" + end + + test "should update Client" do + visit client_url(@client) + click_on "Edit this client", match: :first + + fill_in "Key", with: @client.key + fill_in "Name", with: @client.name + fill_in "Secret", with: @client.secret + fill_in "State", with: @client.state + click_on "Update Client" + + assert_text "Client was successfully updated" + click_on "Back" + end + + test "should destroy Client" do + visit client_url(@client) + click_on "Destroy this client", match: :first + + assert_text "Client was successfully destroyed" + end +end diff --git a/vendor/.keep b/vendor/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/javascript/.keep b/vendor/javascript/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/vendor/javascript/bootstrap.js b/vendor/javascript/bootstrap.js new file mode 100644 index 0000000..832bd00 --- /dev/null +++ b/vendor/javascript/bootstrap.js @@ -0,0 +1,2 @@ +!function (t, e) { "object" == typeof exports && "undefined" != typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : (t = "undefined" != typeof globalThis ? globalThis : t || self).bootstrap = e() }(this, (function () { "use strict"; const t = new Map, e = { set(e, i, n) { t.has(e) || t.set(e, new Map); const s = t.get(e); s.has(i) || 0 === s.size ? s.set(i, n) : console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`) }, get: (e, i) => t.has(e) && t.get(e).get(i) || null, remove(e, i) { if (!t.has(e)) return; const n = t.get(e); n.delete(i), 0 === n.size && t.delete(e) } }, i = "transitionend", n = t => (t && window.CSS && window.CSS.escape && (t = t.replace(/#([^\s"#']+)/g, ((t, e) => `#${CSS.escape(e)}`))), t), s = t => { t.dispatchEvent(new Event(i)) }, o = t => !(!t || "object" != typeof t) && (void 0 !== t.jquery && (t = t[0]), void 0 !== t.nodeType), r = t => o(t) ? t.jquery ? t[0] : t : "string" == typeof t && t.length > 0 ? document.querySelector(n(t)) : null, a = t => { if (!o(t) || 0 === t.getClientRects().length) return !1; const e = "visible" === getComputedStyle(t).getPropertyValue("visibility"), i = t.closest("details:not([open])"); if (!i) return e; if (i !== t) { const e = t.closest("summary"); if (e && e.parentNode !== i) return !1; if (null === e) return !1 } return e }, l = t => !t || t.nodeType !== Node.ELEMENT_NODE || !!t.classList.contains("disabled") || (void 0 !== t.disabled ? t.disabled : t.hasAttribute("disabled") && "false" !== t.getAttribute("disabled")), c = t => { if (!document.documentElement.attachShadow) return null; if ("function" == typeof t.getRootNode) { const e = t.getRootNode(); return e instanceof ShadowRoot ? e : null } return t instanceof ShadowRoot ? t : t.parentNode ? c(t.parentNode) : null }, h = () => { }, d = t => { t.offsetHeight }, u = () => window.jQuery && !document.body.hasAttribute("data-bs-no-jquery") ? window.jQuery : null, f = [], p = () => "rtl" === document.documentElement.dir, m = t => { var e; e = () => { const e = u(); if (e) { const i = t.NAME, n = e.fn[i]; e.fn[i] = t.jQueryInterface, e.fn[i].Constructor = t, e.fn[i].noConflict = () => (e.fn[i] = n, t.jQueryInterface) } }, "loading" === document.readyState ? (f.length || document.addEventListener("DOMContentLoaded", (() => { for (const t of f) t() })), f.push(e)) : e() }, g = (t, e = [], i = t) => "function" == typeof t ? t(...e) : i, _ = (t, e, n = !0) => { if (!n) return void g(t); const o = (t => { if (!t) return 0; let { transitionDuration: e, transitionDelay: i } = window.getComputedStyle(t); const n = Number.parseFloat(e), s = Number.parseFloat(i); return n || s ? (e = e.split(",")[0], i = i.split(",")[0], 1e3 * (Number.parseFloat(e) + Number.parseFloat(i))) : 0 })(e) + 5; let r = !1; const a = ({ target: n }) => { n === e && (r = !0, e.removeEventListener(i, a), g(t)) }; e.addEventListener(i, a), setTimeout((() => { r || s(e) }), o) }, b = (t, e, i, n) => { const s = t.length; let o = t.indexOf(e); return -1 === o ? !i && n ? t[s - 1] : t[0] : (o += i ? 1 : -1, n && (o = (o + s) % s), t[Math.max(0, Math.min(o, s - 1))]) }, v = /[^.]*(?=\..*)\.|.*/, y = /\..*/, w = /::\d+$/, A = {}; let E = 1; const T = { mouseenter: "mouseover", mouseleave: "mouseout" }, C = new Set(["click", "dblclick", "mouseup", "mousedown", "contextmenu", "mousewheel", "DOMMouseScroll", "mouseover", "mouseout", "mousemove", "selectstart", "selectend", "keydown", "keypress", "keyup", "orientationchange", "touchstart", "touchmove", "touchend", "touchcancel", "pointerdown", "pointermove", "pointerup", "pointerleave", "pointercancel", "gesturestart", "gesturechange", "gestureend", "focus", "blur", "change", "reset", "select", "submit", "focusin", "focusout", "load", "unload", "beforeunload", "resize", "move", "DOMContentLoaded", "readystatechange", "error", "abort", "scroll"]); function O(t, e) { return e && `${e}::${E++}` || t.uidEvent || E++ } function x(t) { const e = O(t); return t.uidEvent = e, A[e] = A[e] || {}, A[e] } function k(t, e, i = null) { return Object.values(t).find((t => t.callable === e && t.delegationSelector === i)) } function L(t, e, i) { const n = "string" == typeof e, s = n ? i : e || i; let o = I(t); return C.has(o) || (o = t), [n, s, o] } function S(t, e, i, n, s) { if ("string" != typeof e || !t) return; let [o, r, a] = L(e, i, n); if (e in T) { const t = t => function (e) { if (!e.relatedTarget || e.relatedTarget !== e.delegateTarget && !e.delegateTarget.contains(e.relatedTarget)) return t.call(this, e) }; r = t(r) } const l = x(t), c = l[a] || (l[a] = {}), h = k(c, r, o ? i : null); if (h) return void (h.oneOff = h.oneOff && s); const d = O(r, e.replace(v, "")), u = o ? function (t, e, i) { return function n(s) { const o = t.querySelectorAll(e); for (let { target: r } = s; r && r !== this; r = r.parentNode)for (const a of o) if (a === r) return P(s, { delegateTarget: r }), n.oneOff && N.off(t, s.type, e, i), i.apply(r, [s]) } }(t, i, r) : function (t, e) { return function i(n) { return P(n, { delegateTarget: t }), i.oneOff && N.off(t, n.type, e), e.apply(t, [n]) } }(t, r); u.delegationSelector = o ? i : null, u.callable = r, u.oneOff = s, u.uidEvent = d, c[d] = u, t.addEventListener(a, u, o) } function D(t, e, i, n, s) { const o = k(e[i], n, s); o && (t.removeEventListener(i, o, Boolean(s)), delete e[i][o.uidEvent]) } function $(t, e, i, n) { const s = e[i] || {}; for (const [o, r] of Object.entries(s)) o.includes(n) && D(t, e, i, r.callable, r.delegationSelector) } function I(t) { return t = t.replace(y, ""), T[t] || t } const N = { on(t, e, i, n) { S(t, e, i, n, !1) }, one(t, e, i, n) { S(t, e, i, n, !0) }, off(t, e, i, n) { if ("string" != typeof e || !t) return; const [s, o, r] = L(e, i, n), a = r !== e, l = x(t), c = l[r] || {}, h = e.startsWith("."); if (void 0 === o) { if (h) for (const i of Object.keys(l)) $(t, l, i, e.slice(1)); for (const [i, n] of Object.entries(c)) { const s = i.replace(w, ""); a && !e.includes(s) || D(t, l, r, n.callable, n.delegationSelector) } } else { if (!Object.keys(c).length) return; D(t, l, r, o, s ? i : null) } }, trigger(t, e, i) { if ("string" != typeof e || !t) return null; const n = u(); let s = null, o = !0, r = !0, a = !1; e !== I(e) && n && (s = n.Event(e, i), n(t).trigger(s), o = !s.isPropagationStopped(), r = !s.isImmediatePropagationStopped(), a = s.isDefaultPrevented()); const l = P(new Event(e, { bubbles: o, cancelable: !0 }), i); return a && l.preventDefault(), r && t.dispatchEvent(l), l.defaultPrevented && s && s.preventDefault(), l } }; function P(t, e = {}) { for (const [i, n] of Object.entries(e)) try { t[i] = n } catch (e) { Object.defineProperty(t, i, { configurable: !0, get: () => n }) } return t } function j(t) { if ("true" === t) return !0; if ("false" === t) return !1; if (t === Number(t).toString()) return Number(t); if ("" === t || "null" === t) return null; if ("string" != typeof t) return t; try { return JSON.parse(decodeURIComponent(t)) } catch (e) { return t } } function M(t) { return t.replace(/[A-Z]/g, (t => `-${t.toLowerCase()}`)) } const F = { setDataAttribute(t, e, i) { t.setAttribute(`data-bs-${M(e)}`, i) }, removeDataAttribute(t, e) { t.removeAttribute(`data-bs-${M(e)}`) }, getDataAttributes(t) { if (!t) return {}; const e = {}, i = Object.keys(t.dataset).filter((t => t.startsWith("bs") && !t.startsWith("bsConfig"))); for (const n of i) { let i = n.replace(/^bs/, ""); i = i.charAt(0).toLowerCase() + i.slice(1, i.length), e[i] = j(t.dataset[n]) } return e }, getDataAttribute: (t, e) => j(t.getAttribute(`data-bs-${M(e)}`)) }; class H { static get Default() { return {} } static get DefaultType() { return {} } static get NAME() { throw new Error('You have to implement the static method "NAME", for each component!') } _getConfig(t) { return t = this._mergeConfigObj(t), t = this._configAfterMerge(t), this._typeCheckConfig(t), t } _configAfterMerge(t) { return t } _mergeConfigObj(t, e) { const i = o(e) ? F.getDataAttribute(e, "config") : {}; return { ...this.constructor.Default, ..."object" == typeof i ? i : {}, ...o(e) ? F.getDataAttributes(e) : {}, ..."object" == typeof t ? t : {} } } _typeCheckConfig(t, e = this.constructor.DefaultType) { for (const [n, s] of Object.entries(e)) { const e = t[n], r = o(e) ? "element" : null == (i = e) ? `${i}` : Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase(); if (!new RegExp(s).test(r)) throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${r}" but expected type "${s}".`) } var i } } class W extends H { constructor(t, i) { super(), (t = r(t)) && (this._element = t, this._config = this._getConfig(i), e.set(this._element, this.constructor.DATA_KEY, this)) } dispose() { e.remove(this._element, this.constructor.DATA_KEY), N.off(this._element, this.constructor.EVENT_KEY); for (const t of Object.getOwnPropertyNames(this)) this[t] = null } _queueCallback(t, e, i = !0) { _(t, e, i) } _getConfig(t) { return t = this._mergeConfigObj(t, this._element), t = this._configAfterMerge(t), this._typeCheckConfig(t), t } static getInstance(t) { return e.get(r(t), this.DATA_KEY) } static getOrCreateInstance(t, e = {}) { return this.getInstance(t) || new this(t, "object" == typeof e ? e : null) } static get VERSION() { return "5.3.3" } static get DATA_KEY() { return `bs.${this.NAME}` } static get EVENT_KEY() { return `.${this.DATA_KEY}` } static eventName(t) { return `${t}${this.EVENT_KEY}` } } const B = t => { let e = t.getAttribute("data-bs-target"); if (!e || "#" === e) { let i = t.getAttribute("href"); if (!i || !i.includes("#") && !i.startsWith(".")) return null; i.includes("#") && !i.startsWith("#") && (i = `#${i.split("#")[1]}`), e = i && "#" !== i ? i.trim() : null } return e ? e.split(",").map((t => n(t))).join(",") : null }, z = { find: (t, e = document.documentElement) => [].concat(...Element.prototype.querySelectorAll.call(e, t)), findOne: (t, e = document.documentElement) => Element.prototype.querySelector.call(e, t), children: (t, e) => [].concat(...t.children).filter((t => t.matches(e))), parents(t, e) { const i = []; let n = t.parentNode.closest(e); for (; n;)i.push(n), n = n.parentNode.closest(e); return i }, prev(t, e) { let i = t.previousElementSibling; for (; i;) { if (i.matches(e)) return [i]; i = i.previousElementSibling } return [] }, next(t, e) { let i = t.nextElementSibling; for (; i;) { if (i.matches(e)) return [i]; i = i.nextElementSibling } return [] }, focusableChildren(t) { const e = ["a", "button", "input", "textarea", "select", "details", "[tabindex]", '[contenteditable="true"]'].map((t => `${t}:not([tabindex^="-"])`)).join(","); return this.find(e, t).filter((t => !l(t) && a(t))) }, getSelectorFromElement(t) { const e = B(t); return e && z.findOne(e) ? e : null }, getElementFromSelector(t) { const e = B(t); return e ? z.findOne(e) : null }, getMultipleElementsFromSelector(t) { const e = B(t); return e ? z.find(e) : [] } }, R = (t, e = "hide") => { const i = `click.dismiss${t.EVENT_KEY}`, n = t.NAME; N.on(document, i, `[data-bs-dismiss="${n}"]`, (function (i) { if (["A", "AREA"].includes(this.tagName) && i.preventDefault(), l(this)) return; const s = z.getElementFromSelector(this) || this.closest(`.${n}`); t.getOrCreateInstance(s)[e]() })) }, q = ".bs.alert", V = `close${q}`, K = `closed${q}`; class Q extends W { static get NAME() { return "alert" } close() { if (N.trigger(this._element, V).defaultPrevented) return; this._element.classList.remove("show"); const t = this._element.classList.contains("fade"); this._queueCallback((() => this._destroyElement()), this._element, t) } _destroyElement() { this._element.remove(), N.trigger(this._element, K), this.dispose() } static jQueryInterface(t) { return this.each((function () { const e = Q.getOrCreateInstance(this); if ("string" == typeof t) { if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) throw new TypeError(`No method named "${t}"`); e[t](this) } })) } } R(Q, "close"), m(Q); const X = '[data-bs-toggle="button"]'; class Y extends W { static get NAME() { return "button" } toggle() { this._element.setAttribute("aria-pressed", this._element.classList.toggle("active")) } static jQueryInterface(t) { return this.each((function () { const e = Y.getOrCreateInstance(this); "toggle" === t && e[t]() })) } } N.on(document, "click.bs.button.data-api", X, (t => { t.preventDefault(); const e = t.target.closest(X); Y.getOrCreateInstance(e).toggle() })), m(Y); const U = ".bs.swipe", G = `touchstart${U}`, J = `touchmove${U}`, Z = `touchend${U}`, tt = `pointerdown${U}`, et = `pointerup${U}`, it = { endCallback: null, leftCallback: null, rightCallback: null }, nt = { endCallback: "(function|null)", leftCallback: "(function|null)", rightCallback: "(function|null)" }; class st extends H { constructor(t, e) { super(), this._element = t, t && st.isSupported() && (this._config = this._getConfig(e), this._deltaX = 0, this._supportPointerEvents = Boolean(window.PointerEvent), this._initEvents()) } static get Default() { return it } static get DefaultType() { return nt } static get NAME() { return "swipe" } dispose() { N.off(this._element, U) } _start(t) { this._supportPointerEvents ? this._eventIsPointerPenTouch(t) && (this._deltaX = t.clientX) : this._deltaX = t.touches[0].clientX } _end(t) { this._eventIsPointerPenTouch(t) && (this._deltaX = t.clientX - this._deltaX), this._handleSwipe(), g(this._config.endCallback) } _move(t) { this._deltaX = t.touches && t.touches.length > 1 ? 0 : t.touches[0].clientX - this._deltaX } _handleSwipe() { const t = Math.abs(this._deltaX); if (t <= 40) return; const e = t / this._deltaX; this._deltaX = 0, e && g(e > 0 ? this._config.rightCallback : this._config.leftCallback) } _initEvents() { this._supportPointerEvents ? (N.on(this._element, tt, (t => this._start(t))), N.on(this._element, et, (t => this._end(t))), this._element.classList.add("pointer-event")) : (N.on(this._element, G, (t => this._start(t))), N.on(this._element, J, (t => this._move(t))), N.on(this._element, Z, (t => this._end(t)))) } _eventIsPointerPenTouch(t) { return this._supportPointerEvents && ("pen" === t.pointerType || "touch" === t.pointerType) } static isSupported() { return "ontouchstart" in document.documentElement || navigator.maxTouchPoints > 0 } } const ot = ".bs.carousel", rt = ".data-api", at = "next", lt = "prev", ct = "left", ht = "right", dt = `slide${ot}`, ut = `slid${ot}`, ft = `keydown${ot}`, pt = `mouseenter${ot}`, mt = `mouseleave${ot}`, gt = `dragstart${ot}`, _t = `load${ot}${rt}`, bt = `click${ot}${rt}`, vt = "carousel", yt = "active", wt = ".active", At = ".carousel-item", Et = wt + At, Tt = { ArrowLeft: ht, ArrowRight: ct }, Ct = { interval: 5e3, keyboard: !0, pause: "hover", ride: !1, touch: !0, wrap: !0 }, Ot = { interval: "(number|boolean)", keyboard: "boolean", pause: "(string|boolean)", ride: "(boolean|string)", touch: "boolean", wrap: "boolean" }; class xt extends W { constructor(t, e) { super(t, e), this._interval = null, this._activeElement = null, this._isSliding = !1, this.touchTimeout = null, this._swipeHelper = null, this._indicatorsElement = z.findOne(".carousel-indicators", this._element), this._addEventListeners(), this._config.ride === vt && this.cycle() } static get Default() { return Ct } static get DefaultType() { return Ot } static get NAME() { return "carousel" } next() { this._slide(at) } nextWhenVisible() { !document.hidden && a(this._element) && this.next() } prev() { this._slide(lt) } pause() { this._isSliding && s(this._element), this._clearInterval() } cycle() { this._clearInterval(), this._updateInterval(), this._interval = setInterval((() => this.nextWhenVisible()), this._config.interval) } _maybeEnableCycle() { this._config.ride && (this._isSliding ? N.one(this._element, ut, (() => this.cycle())) : this.cycle()) } to(t) { const e = this._getItems(); if (t > e.length - 1 || t < 0) return; if (this._isSliding) return void N.one(this._element, ut, (() => this.to(t))); const i = this._getItemIndex(this._getActive()); if (i === t) return; const n = t > i ? at : lt; this._slide(n, e[t]) } dispose() { this._swipeHelper && this._swipeHelper.dispose(), super.dispose() } _configAfterMerge(t) { return t.defaultInterval = t.interval, t } _addEventListeners() { this._config.keyboard && N.on(this._element, ft, (t => this._keydown(t))), "hover" === this._config.pause && (N.on(this._element, pt, (() => this.pause())), N.on(this._element, mt, (() => this._maybeEnableCycle()))), this._config.touch && st.isSupported() && this._addTouchEventListeners() } _addTouchEventListeners() { for (const t of z.find(".carousel-item img", this._element)) N.on(t, gt, (t => t.preventDefault())); const t = { leftCallback: () => this._slide(this._directionToOrder(ct)), rightCallback: () => this._slide(this._directionToOrder(ht)), endCallback: () => { "hover" === this._config.pause && (this.pause(), this.touchTimeout && clearTimeout(this.touchTimeout), this.touchTimeout = setTimeout((() => this._maybeEnableCycle()), 500 + this._config.interval)) } }; this._swipeHelper = new st(this._element, t) } _keydown(t) { if (/input|textarea/i.test(t.target.tagName)) return; const e = Tt[t.key]; e && (t.preventDefault(), this._slide(this._directionToOrder(e))) } _getItemIndex(t) { return this._getItems().indexOf(t) } _setActiveIndicatorElement(t) { if (!this._indicatorsElement) return; const e = z.findOne(wt, this._indicatorsElement); e.classList.remove(yt), e.removeAttribute("aria-current"); const i = z.findOne(`[data-bs-slide-to="${t}"]`, this._indicatorsElement); i && (i.classList.add(yt), i.setAttribute("aria-current", "true")) } _updateInterval() { const t = this._activeElement || this._getActive(); if (!t) return; const e = Number.parseInt(t.getAttribute("data-bs-interval"), 10); this._config.interval = e || this._config.defaultInterval } _slide(t, e = null) { if (this._isSliding) return; const i = this._getActive(), n = t === at, s = e || b(this._getItems(), i, n, this._config.wrap); if (s === i) return; const o = this._getItemIndex(s), r = e => N.trigger(this._element, e, { relatedTarget: s, direction: this._orderToDirection(t), from: this._getItemIndex(i), to: o }); if (r(dt).defaultPrevented) return; if (!i || !s) return; const a = Boolean(this._interval); this.pause(), this._isSliding = !0, this._setActiveIndicatorElement(o), this._activeElement = s; const l = n ? "carousel-item-start" : "carousel-item-end", c = n ? "carousel-item-next" : "carousel-item-prev"; s.classList.add(c), d(s), i.classList.add(l), s.classList.add(l), this._queueCallback((() => { s.classList.remove(l, c), s.classList.add(yt), i.classList.remove(yt, c, l), this._isSliding = !1, r(ut) }), i, this._isAnimated()), a && this.cycle() } _isAnimated() { return this._element.classList.contains("slide") } _getActive() { return z.findOne(Et, this._element) } _getItems() { return z.find(At, this._element) } _clearInterval() { this._interval && (clearInterval(this._interval), this._interval = null) } _directionToOrder(t) { return p() ? t === ct ? lt : at : t === ct ? at : lt } _orderToDirection(t) { return p() ? t === lt ? ct : ht : t === lt ? ht : ct } static jQueryInterface(t) { return this.each((function () { const e = xt.getOrCreateInstance(this, t); if ("number" != typeof t) { if ("string" == typeof t) { if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) throw new TypeError(`No method named "${t}"`); e[t]() } } else e.to(t) })) } } N.on(document, bt, "[data-bs-slide], [data-bs-slide-to]", (function (t) { const e = z.getElementFromSelector(this); if (!e || !e.classList.contains(vt)) return; t.preventDefault(); const i = xt.getOrCreateInstance(e), n = this.getAttribute("data-bs-slide-to"); return n ? (i.to(n), void i._maybeEnableCycle()) : "next" === F.getDataAttribute(this, "slide") ? (i.next(), void i._maybeEnableCycle()) : (i.prev(), void i._maybeEnableCycle()) })), N.on(window, _t, (() => { const t = z.find('[data-bs-ride="carousel"]'); for (const e of t) xt.getOrCreateInstance(e) })), m(xt); const kt = ".bs.collapse", Lt = `show${kt}`, St = `shown${kt}`, Dt = `hide${kt}`, $t = `hidden${kt}`, It = `click${kt}.data-api`, Nt = "show", Pt = "collapse", jt = "collapsing", Mt = `:scope .${Pt} .${Pt}`, Ft = '[data-bs-toggle="collapse"]', Ht = { parent: null, toggle: !0 }, Wt = { parent: "(null|element)", toggle: "boolean" }; class Bt extends W { constructor(t, e) { super(t, e), this._isTransitioning = !1, this._triggerArray = []; const i = z.find(Ft); for (const t of i) { const e = z.getSelectorFromElement(t), i = z.find(e).filter((t => t === this._element)); null !== e && i.length && this._triggerArray.push(t) } this._initializeChildren(), this._config.parent || this._addAriaAndCollapsedClass(this._triggerArray, this._isShown()), this._config.toggle && this.toggle() } static get Default() { return Ht } static get DefaultType() { return Wt } static get NAME() { return "collapse" } toggle() { this._isShown() ? this.hide() : this.show() } show() { if (this._isTransitioning || this._isShown()) return; let t = []; if (this._config.parent && (t = this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t => t !== this._element)).map((t => Bt.getOrCreateInstance(t, { toggle: !1 })))), t.length && t[0]._isTransitioning) return; if (N.trigger(this._element, Lt).defaultPrevented) return; for (const e of t) e.hide(); const e = this._getDimension(); this._element.classList.remove(Pt), this._element.classList.add(jt), this._element.style[e] = 0, this._addAriaAndCollapsedClass(this._triggerArray, !0), this._isTransitioning = !0; const i = `scroll${e[0].toUpperCase() + e.slice(1)}`; this._queueCallback((() => { this._isTransitioning = !1, this._element.classList.remove(jt), this._element.classList.add(Pt, Nt), this._element.style[e] = "", N.trigger(this._element, St) }), this._element, !0), this._element.style[e] = `${this._element[i]}px` } hide() { if (this._isTransitioning || !this._isShown()) return; if (N.trigger(this._element, Dt).defaultPrevented) return; const t = this._getDimension(); this._element.style[t] = `${this._element.getBoundingClientRect()[t]}px`, d(this._element), this._element.classList.add(jt), this._element.classList.remove(Pt, Nt); for (const t of this._triggerArray) { const e = z.getElementFromSelector(t); e && !this._isShown(e) && this._addAriaAndCollapsedClass([t], !1) } this._isTransitioning = !0, this._element.style[t] = "", this._queueCallback((() => { this._isTransitioning = !1, this._element.classList.remove(jt), this._element.classList.add(Pt), N.trigger(this._element, $t) }), this._element, !0) } _isShown(t = this._element) { return t.classList.contains(Nt) } _configAfterMerge(t) { return t.toggle = Boolean(t.toggle), t.parent = r(t.parent), t } _getDimension() { return this._element.classList.contains("collapse-horizontal") ? "width" : "height" } _initializeChildren() { if (!this._config.parent) return; const t = this._getFirstLevelChildren(Ft); for (const e of t) { const t = z.getElementFromSelector(e); t && this._addAriaAndCollapsedClass([e], this._isShown(t)) } } _getFirstLevelChildren(t) { const e = z.find(Mt, this._config.parent); return z.find(t, this._config.parent).filter((t => !e.includes(t))) } _addAriaAndCollapsedClass(t, e) { if (t.length) for (const i of t) i.classList.toggle("collapsed", !e), i.setAttribute("aria-expanded", e) } static jQueryInterface(t) { const e = {}; return "string" == typeof t && /show|hide/.test(t) && (e.toggle = !1), this.each((function () { const i = Bt.getOrCreateInstance(this, e); if ("string" == typeof t) { if (void 0 === i[t]) throw new TypeError(`No method named "${t}"`); i[t]() } })) } } N.on(document, It, Ft, (function (t) { ("A" === t.target.tagName || t.delegateTarget && "A" === t.delegateTarget.tagName) && t.preventDefault(); for (const t of z.getMultipleElementsFromSelector(this)) Bt.getOrCreateInstance(t, { toggle: !1 }).toggle() })), m(Bt); var zt = "top", Rt = "bottom", qt = "right", Vt = "left", Kt = "auto", Qt = [zt, Rt, qt, Vt], Xt = "start", Yt = "end", Ut = "clippingParents", Gt = "viewport", Jt = "popper", Zt = "reference", te = Qt.reduce((function (t, e) { return t.concat([e + "-" + Xt, e + "-" + Yt]) }), []), ee = [].concat(Qt, [Kt]).reduce((function (t, e) { return t.concat([e, e + "-" + Xt, e + "-" + Yt]) }), []), ie = "beforeRead", ne = "read", se = "afterRead", oe = "beforeMain", re = "main", ae = "afterMain", le = "beforeWrite", ce = "write", he = "afterWrite", de = [ie, ne, se, oe, re, ae, le, ce, he]; function ue(t) { return t ? (t.nodeName || "").toLowerCase() : null } function fe(t) { if (null == t) return window; if ("[object Window]" !== t.toString()) { var e = t.ownerDocument; return e && e.defaultView || window } return t } function pe(t) { return t instanceof fe(t).Element || t instanceof Element } function me(t) { return t instanceof fe(t).HTMLElement || t instanceof HTMLElement } function ge(t) { return "undefined" != typeof ShadowRoot && (t instanceof fe(t).ShadowRoot || t instanceof ShadowRoot) } const _e = { name: "applyStyles", enabled: !0, phase: "write", fn: function (t) { var e = t.state; Object.keys(e.elements).forEach((function (t) { var i = e.styles[t] || {}, n = e.attributes[t] || {}, s = e.elements[t]; me(s) && ue(s) && (Object.assign(s.style, i), Object.keys(n).forEach((function (t) { var e = n[t]; !1 === e ? s.removeAttribute(t) : s.setAttribute(t, !0 === e ? "" : e) }))) })) }, effect: function (t) { var e = t.state, i = { popper: { position: e.options.strategy, left: "0", top: "0", margin: "0" }, arrow: { position: "absolute" }, reference: {} }; return Object.assign(e.elements.popper.style, i.popper), e.styles = i, e.elements.arrow && Object.assign(e.elements.arrow.style, i.arrow), function () { Object.keys(e.elements).forEach((function (t) { var n = e.elements[t], s = e.attributes[t] || {}, o = Object.keys(e.styles.hasOwnProperty(t) ? e.styles[t] : i[t]).reduce((function (t, e) { return t[e] = "", t }), {}); me(n) && ue(n) && (Object.assign(n.style, o), Object.keys(s).forEach((function (t) { n.removeAttribute(t) }))) })) } }, requires: ["computeStyles"] }; function be(t) { return t.split("-")[0] } var ve = Math.max, ye = Math.min, we = Math.round; function Ae() { var t = navigator.userAgentData; return null != t && t.brands && Array.isArray(t.brands) ? t.brands.map((function (t) { return t.brand + "/" + t.version })).join(" ") : navigator.userAgent } function Ee() { return !/^((?!chrome|android).)*safari/i.test(Ae()) } function Te(t, e, i) { void 0 === e && (e = !1), void 0 === i && (i = !1); var n = t.getBoundingClientRect(), s = 1, o = 1; e && me(t) && (s = t.offsetWidth > 0 && we(n.width) / t.offsetWidth || 1, o = t.offsetHeight > 0 && we(n.height) / t.offsetHeight || 1); var r = (pe(t) ? fe(t) : window).visualViewport, a = !Ee() && i, l = (n.left + (a && r ? r.offsetLeft : 0)) / s, c = (n.top + (a && r ? r.offsetTop : 0)) / o, h = n.width / s, d = n.height / o; return { width: h, height: d, top: c, right: l + h, bottom: c + d, left: l, x: l, y: c } } function Ce(t) { var e = Te(t), i = t.offsetWidth, n = t.offsetHeight; return Math.abs(e.width - i) <= 1 && (i = e.width), Math.abs(e.height - n) <= 1 && (n = e.height), { x: t.offsetLeft, y: t.offsetTop, width: i, height: n } } function Oe(t, e) { var i = e.getRootNode && e.getRootNode(); if (t.contains(e)) return !0; if (i && ge(i)) { var n = e; do { if (n && t.isSameNode(n)) return !0; n = n.parentNode || n.host } while (n) } return !1 } function xe(t) { return fe(t).getComputedStyle(t) } function ke(t) { return ["table", "td", "th"].indexOf(ue(t)) >= 0 } function Le(t) { return ((pe(t) ? t.ownerDocument : t.document) || window.document).documentElement } function Se(t) { return "html" === ue(t) ? t : t.assignedSlot || t.parentNode || (ge(t) ? t.host : null) || Le(t) } function De(t) { return me(t) && "fixed" !== xe(t).position ? t.offsetParent : null } function $e(t) { for (var e = fe(t), i = De(t); i && ke(i) && "static" === xe(i).position;)i = De(i); return i && ("html" === ue(i) || "body" === ue(i) && "static" === xe(i).position) ? e : i || function (t) { var e = /firefox/i.test(Ae()); if (/Trident/i.test(Ae()) && me(t) && "fixed" === xe(t).position) return null; var i = Se(t); for (ge(i) && (i = i.host); me(i) && ["html", "body"].indexOf(ue(i)) < 0;) { var n = xe(i); if ("none" !== n.transform || "none" !== n.perspective || "paint" === n.contain || -1 !== ["transform", "perspective"].indexOf(n.willChange) || e && "filter" === n.willChange || e && n.filter && "none" !== n.filter) return i; i = i.parentNode } return null }(t) || e } function Ie(t) { return ["top", "bottom"].indexOf(t) >= 0 ? "x" : "y" } function Ne(t, e, i) { return ve(t, ye(e, i)) } function Pe(t) { return Object.assign({}, { top: 0, right: 0, bottom: 0, left: 0 }, t) } function je(t, e) { return e.reduce((function (e, i) { return e[i] = t, e }), {}) } const Me = { name: "arrow", enabled: !0, phase: "main", fn: function (t) { var e, i = t.state, n = t.name, s = t.options, o = i.elements.arrow, r = i.modifiersData.popperOffsets, a = be(i.placement), l = Ie(a), c = [Vt, qt].indexOf(a) >= 0 ? "height" : "width"; if (o && r) { var h = function (t, e) { return Pe("number" != typeof (t = "function" == typeof t ? t(Object.assign({}, e.rects, { placement: e.placement })) : t) ? t : je(t, Qt)) }(s.padding, i), d = Ce(o), u = "y" === l ? zt : Vt, f = "y" === l ? Rt : qt, p = i.rects.reference[c] + i.rects.reference[l] - r[l] - i.rects.popper[c], m = r[l] - i.rects.reference[l], g = $e(o), _ = g ? "y" === l ? g.clientHeight || 0 : g.clientWidth || 0 : 0, b = p / 2 - m / 2, v = h[u], y = _ - d[c] - h[f], w = _ / 2 - d[c] / 2 + b, A = Ne(v, w, y), E = l; i.modifiersData[n] = ((e = {})[E] = A, e.centerOffset = A - w, e) } }, effect: function (t) { var e = t.state, i = t.options.element, n = void 0 === i ? "[data-popper-arrow]" : i; null != n && ("string" != typeof n || (n = e.elements.popper.querySelector(n))) && Oe(e.elements.popper, n) && (e.elements.arrow = n) }, requires: ["popperOffsets"], requiresIfExists: ["preventOverflow"] }; function Fe(t) { return t.split("-")[1] } var He = { top: "auto", right: "auto", bottom: "auto", left: "auto" }; function We(t) { var e, i = t.popper, n = t.popperRect, s = t.placement, o = t.variation, r = t.offsets, a = t.position, l = t.gpuAcceleration, c = t.adaptive, h = t.roundOffsets, d = t.isFixed, u = r.x, f = void 0 === u ? 0 : u, p = r.y, m = void 0 === p ? 0 : p, g = "function" == typeof h ? h({ x: f, y: m }) : { x: f, y: m }; f = g.x, m = g.y; var _ = r.hasOwnProperty("x"), b = r.hasOwnProperty("y"), v = Vt, y = zt, w = window; if (c) { var A = $e(i), E = "clientHeight", T = "clientWidth"; A === fe(i) && "static" !== xe(A = Le(i)).position && "absolute" === a && (E = "scrollHeight", T = "scrollWidth"), (s === zt || (s === Vt || s === qt) && o === Yt) && (y = Rt, m -= (d && A === w && w.visualViewport ? w.visualViewport.height : A[E]) - n.height, m *= l ? 1 : -1), s !== Vt && (s !== zt && s !== Rt || o !== Yt) || (v = qt, f -= (d && A === w && w.visualViewport ? w.visualViewport.width : A[T]) - n.width, f *= l ? 1 : -1) } var C, O = Object.assign({ position: a }, c && He), x = !0 === h ? function (t, e) { var i = t.x, n = t.y, s = e.devicePixelRatio || 1; return { x: we(i * s) / s || 0, y: we(n * s) / s || 0 } }({ x: f, y: m }, fe(i)) : { x: f, y: m }; return f = x.x, m = x.y, l ? Object.assign({}, O, ((C = {})[y] = b ? "0" : "", C[v] = _ ? "0" : "", C.transform = (w.devicePixelRatio || 1) <= 1 ? "translate(" + f + "px, " + m + "px)" : "translate3d(" + f + "px, " + m + "px, 0)", C)) : Object.assign({}, O, ((e = {})[y] = b ? m + "px" : "", e[v] = _ ? f + "px" : "", e.transform = "", e)) } const Be = { name: "computeStyles", enabled: !0, phase: "beforeWrite", fn: function (t) { var e = t.state, i = t.options, n = i.gpuAcceleration, s = void 0 === n || n, o = i.adaptive, r = void 0 === o || o, a = i.roundOffsets, l = void 0 === a || a, c = { placement: be(e.placement), variation: Fe(e.placement), popper: e.elements.popper, popperRect: e.rects.popper, gpuAcceleration: s, isFixed: "fixed" === e.options.strategy }; null != e.modifiersData.popperOffsets && (e.styles.popper = Object.assign({}, e.styles.popper, We(Object.assign({}, c, { offsets: e.modifiersData.popperOffsets, position: e.options.strategy, adaptive: r, roundOffsets: l })))), null != e.modifiersData.arrow && (e.styles.arrow = Object.assign({}, e.styles.arrow, We(Object.assign({}, c, { offsets: e.modifiersData.arrow, position: "absolute", adaptive: !1, roundOffsets: l })))), e.attributes.popper = Object.assign({}, e.attributes.popper, { "data-popper-placement": e.placement }) }, data: {} }; var ze = { passive: !0 }; const Re = { name: "eventListeners", enabled: !0, phase: "write", fn: function () { }, effect: function (t) { var e = t.state, i = t.instance, n = t.options, s = n.scroll, o = void 0 === s || s, r = n.resize, a = void 0 === r || r, l = fe(e.elements.popper), c = [].concat(e.scrollParents.reference, e.scrollParents.popper); return o && c.forEach((function (t) { t.addEventListener("scroll", i.update, ze) })), a && l.addEventListener("resize", i.update, ze), function () { o && c.forEach((function (t) { t.removeEventListener("scroll", i.update, ze) })), a && l.removeEventListener("resize", i.update, ze) } }, data: {} }; var qe = { left: "right", right: "left", bottom: "top", top: "bottom" }; function Ve(t) { return t.replace(/left|right|bottom|top/g, (function (t) { return qe[t] })) } var Ke = { start: "end", end: "start" }; function Qe(t) { return t.replace(/start|end/g, (function (t) { return Ke[t] })) } function Xe(t) { var e = fe(t); return { scrollLeft: e.pageXOffset, scrollTop: e.pageYOffset } } function Ye(t) { return Te(Le(t)).left + Xe(t).scrollLeft } function Ue(t) { var e = xe(t), i = e.overflow, n = e.overflowX, s = e.overflowY; return /auto|scroll|overlay|hidden/.test(i + s + n) } function Ge(t) { return ["html", "body", "#document"].indexOf(ue(t)) >= 0 ? t.ownerDocument.body : me(t) && Ue(t) ? t : Ge(Se(t)) } function Je(t, e) { var i; void 0 === e && (e = []); var n = Ge(t), s = n === (null == (i = t.ownerDocument) ? void 0 : i.body), o = fe(n), r = s ? [o].concat(o.visualViewport || [], Ue(n) ? n : []) : n, a = e.concat(r); return s ? a : a.concat(Je(Se(r))) } function Ze(t) { return Object.assign({}, t, { left: t.x, top: t.y, right: t.x + t.width, bottom: t.y + t.height }) } function ti(t, e, i) { return e === Gt ? Ze(function (t, e) { var i = fe(t), n = Le(t), s = i.visualViewport, o = n.clientWidth, r = n.clientHeight, a = 0, l = 0; if (s) { o = s.width, r = s.height; var c = Ee(); (c || !c && "fixed" === e) && (a = s.offsetLeft, l = s.offsetTop) } return { width: o, height: r, x: a + Ye(t), y: l } }(t, i)) : pe(e) ? function (t, e) { var i = Te(t, !1, "fixed" === e); return i.top = i.top + t.clientTop, i.left = i.left + t.clientLeft, i.bottom = i.top + t.clientHeight, i.right = i.left + t.clientWidth, i.width = t.clientWidth, i.height = t.clientHeight, i.x = i.left, i.y = i.top, i }(e, i) : Ze(function (t) { var e, i = Le(t), n = Xe(t), s = null == (e = t.ownerDocument) ? void 0 : e.body, o = ve(i.scrollWidth, i.clientWidth, s ? s.scrollWidth : 0, s ? s.clientWidth : 0), r = ve(i.scrollHeight, i.clientHeight, s ? s.scrollHeight : 0, s ? s.clientHeight : 0), a = -n.scrollLeft + Ye(t), l = -n.scrollTop; return "rtl" === xe(s || i).direction && (a += ve(i.clientWidth, s ? s.clientWidth : 0) - o), { width: o, height: r, x: a, y: l } }(Le(t))) } function ei(t) { var e, i = t.reference, n = t.element, s = t.placement, o = s ? be(s) : null, r = s ? Fe(s) : null, a = i.x + i.width / 2 - n.width / 2, l = i.y + i.height / 2 - n.height / 2; switch (o) { case zt: e = { x: a, y: i.y - n.height }; break; case Rt: e = { x: a, y: i.y + i.height }; break; case qt: e = { x: i.x + i.width, y: l }; break; case Vt: e = { x: i.x - n.width, y: l }; break; default: e = { x: i.x, y: i.y } }var c = o ? Ie(o) : null; if (null != c) { var h = "y" === c ? "height" : "width"; switch (r) { case Xt: e[c] = e[c] - (i[h] / 2 - n[h] / 2); break; case Yt: e[c] = e[c] + (i[h] / 2 - n[h] / 2) } } return e } function ii(t, e) { void 0 === e && (e = {}); var i = e, n = i.placement, s = void 0 === n ? t.placement : n, o = i.strategy, r = void 0 === o ? t.strategy : o, a = i.boundary, l = void 0 === a ? Ut : a, c = i.rootBoundary, h = void 0 === c ? Gt : c, d = i.elementContext, u = void 0 === d ? Jt : d, f = i.altBoundary, p = void 0 !== f && f, m = i.padding, g = void 0 === m ? 0 : m, _ = Pe("number" != typeof g ? g : je(g, Qt)), b = u === Jt ? Zt : Jt, v = t.rects.popper, y = t.elements[p ? b : u], w = function (t, e, i, n) { var s = "clippingParents" === e ? function (t) { var e = Je(Se(t)), i = ["absolute", "fixed"].indexOf(xe(t).position) >= 0 && me(t) ? $e(t) : t; return pe(i) ? e.filter((function (t) { return pe(t) && Oe(t, i) && "body" !== ue(t) })) : [] }(t) : [].concat(e), o = [].concat(s, [i]), r = o[0], a = o.reduce((function (e, i) { var s = ti(t, i, n); return e.top = ve(s.top, e.top), e.right = ye(s.right, e.right), e.bottom = ye(s.bottom, e.bottom), e.left = ve(s.left, e.left), e }), ti(t, r, n)); return a.width = a.right - a.left, a.height = a.bottom - a.top, a.x = a.left, a.y = a.top, a }(pe(y) ? y : y.contextElement || Le(t.elements.popper), l, h, r), A = Te(t.elements.reference), E = ei({ reference: A, element: v, strategy: "absolute", placement: s }), T = Ze(Object.assign({}, v, E)), C = u === Jt ? T : A, O = { top: w.top - C.top + _.top, bottom: C.bottom - w.bottom + _.bottom, left: w.left - C.left + _.left, right: C.right - w.right + _.right }, x = t.modifiersData.offset; if (u === Jt && x) { var k = x[s]; Object.keys(O).forEach((function (t) { var e = [qt, Rt].indexOf(t) >= 0 ? 1 : -1, i = [zt, Rt].indexOf(t) >= 0 ? "y" : "x"; O[t] += k[i] * e })) } return O } function ni(t, e) { void 0 === e && (e = {}); var i = e, n = i.placement, s = i.boundary, o = i.rootBoundary, r = i.padding, a = i.flipVariations, l = i.allowedAutoPlacements, c = void 0 === l ? ee : l, h = Fe(n), d = h ? a ? te : te.filter((function (t) { return Fe(t) === h })) : Qt, u = d.filter((function (t) { return c.indexOf(t) >= 0 })); 0 === u.length && (u = d); var f = u.reduce((function (e, i) { return e[i] = ii(t, { placement: i, boundary: s, rootBoundary: o, padding: r })[be(i)], e }), {}); return Object.keys(f).sort((function (t, e) { return f[t] - f[e] })) } const si = { name: "flip", enabled: !0, phase: "main", fn: function (t) { var e = t.state, i = t.options, n = t.name; if (!e.modifiersData[n]._skip) { for (var s = i.mainAxis, o = void 0 === s || s, r = i.altAxis, a = void 0 === r || r, l = i.fallbackPlacements, c = i.padding, h = i.boundary, d = i.rootBoundary, u = i.altBoundary, f = i.flipVariations, p = void 0 === f || f, m = i.allowedAutoPlacements, g = e.options.placement, _ = be(g), b = l || (_ !== g && p ? function (t) { if (be(t) === Kt) return []; var e = Ve(t); return [Qe(t), e, Qe(e)] }(g) : [Ve(g)]), v = [g].concat(b).reduce((function (t, i) { return t.concat(be(i) === Kt ? ni(e, { placement: i, boundary: h, rootBoundary: d, padding: c, flipVariations: p, allowedAutoPlacements: m }) : i) }), []), y = e.rects.reference, w = e.rects.popper, A = new Map, E = !0, T = v[0], C = 0; C < v.length; C++) { var O = v[C], x = be(O), k = Fe(O) === Xt, L = [zt, Rt].indexOf(x) >= 0, S = L ? "width" : "height", D = ii(e, { placement: O, boundary: h, rootBoundary: d, altBoundary: u, padding: c }), $ = L ? k ? qt : Vt : k ? Rt : zt; y[S] > w[S] && ($ = Ve($)); var I = Ve($), N = []; if (o && N.push(D[x] <= 0), a && N.push(D[$] <= 0, D[I] <= 0), N.every((function (t) { return t }))) { T = O, E = !1; break } A.set(O, N) } if (E) for (var P = function (t) { var e = v.find((function (e) { var i = A.get(e); if (i) return i.slice(0, t).every((function (t) { return t })) })); if (e) return T = e, "break" }, j = p ? 3 : 1; j > 0 && "break" !== P(j); j--); e.placement !== T && (e.modifiersData[n]._skip = !0, e.placement = T, e.reset = !0) } }, requiresIfExists: ["offset"], data: { _skip: !1 } }; function oi(t, e, i) { return void 0 === i && (i = { x: 0, y: 0 }), { top: t.top - e.height - i.y, right: t.right - e.width + i.x, bottom: t.bottom - e.height + i.y, left: t.left - e.width - i.x } } function ri(t) { return [zt, qt, Rt, Vt].some((function (e) { return t[e] >= 0 })) } const ai = { name: "hide", enabled: !0, phase: "main", requiresIfExists: ["preventOverflow"], fn: function (t) { var e = t.state, i = t.name, n = e.rects.reference, s = e.rects.popper, o = e.modifiersData.preventOverflow, r = ii(e, { elementContext: "reference" }), a = ii(e, { altBoundary: !0 }), l = oi(r, n), c = oi(a, s, o), h = ri(l), d = ri(c); e.modifiersData[i] = { referenceClippingOffsets: l, popperEscapeOffsets: c, isReferenceHidden: h, hasPopperEscaped: d }, e.attributes.popper = Object.assign({}, e.attributes.popper, { "data-popper-reference-hidden": h, "data-popper-escaped": d }) } }, li = { name: "offset", enabled: !0, phase: "main", requires: ["popperOffsets"], fn: function (t) { var e = t.state, i = t.options, n = t.name, s = i.offset, o = void 0 === s ? [0, 0] : s, r = ee.reduce((function (t, i) { return t[i] = function (t, e, i) { var n = be(t), s = [Vt, zt].indexOf(n) >= 0 ? -1 : 1, o = "function" == typeof i ? i(Object.assign({}, e, { placement: t })) : i, r = o[0], a = o[1]; return r = r || 0, a = (a || 0) * s, [Vt, qt].indexOf(n) >= 0 ? { x: a, y: r } : { x: r, y: a } }(i, e.rects, o), t }), {}), a = r[e.placement], l = a.x, c = a.y; null != e.modifiersData.popperOffsets && (e.modifiersData.popperOffsets.x += l, e.modifiersData.popperOffsets.y += c), e.modifiersData[n] = r } }, ci = { name: "popperOffsets", enabled: !0, phase: "read", fn: function (t) { var e = t.state, i = t.name; e.modifiersData[i] = ei({ reference: e.rects.reference, element: e.rects.popper, strategy: "absolute", placement: e.placement }) }, data: {} }, hi = { name: "preventOverflow", enabled: !0, phase: "main", fn: function (t) { var e = t.state, i = t.options, n = t.name, s = i.mainAxis, o = void 0 === s || s, r = i.altAxis, a = void 0 !== r && r, l = i.boundary, c = i.rootBoundary, h = i.altBoundary, d = i.padding, u = i.tether, f = void 0 === u || u, p = i.tetherOffset, m = void 0 === p ? 0 : p, g = ii(e, { boundary: l, rootBoundary: c, padding: d, altBoundary: h }), _ = be(e.placement), b = Fe(e.placement), v = !b, y = Ie(_), w = "x" === y ? "y" : "x", A = e.modifiersData.popperOffsets, E = e.rects.reference, T = e.rects.popper, C = "function" == typeof m ? m(Object.assign({}, e.rects, { placement: e.placement })) : m, O = "number" == typeof C ? { mainAxis: C, altAxis: C } : Object.assign({ mainAxis: 0, altAxis: 0 }, C), x = e.modifiersData.offset ? e.modifiersData.offset[e.placement] : null, k = { x: 0, y: 0 }; if (A) { if (o) { var L, S = "y" === y ? zt : Vt, D = "y" === y ? Rt : qt, $ = "y" === y ? "height" : "width", I = A[y], N = I + g[S], P = I - g[D], j = f ? -T[$] / 2 : 0, M = b === Xt ? E[$] : T[$], F = b === Xt ? -T[$] : -E[$], H = e.elements.arrow, W = f && H ? Ce(H) : { width: 0, height: 0 }, B = e.modifiersData["arrow#persistent"] ? e.modifiersData["arrow#persistent"].padding : { top: 0, right: 0, bottom: 0, left: 0 }, z = B[S], R = B[D], q = Ne(0, E[$], W[$]), V = v ? E[$] / 2 - j - q - z - O.mainAxis : M - q - z - O.mainAxis, K = v ? -E[$] / 2 + j + q + R + O.mainAxis : F + q + R + O.mainAxis, Q = e.elements.arrow && $e(e.elements.arrow), X = Q ? "y" === y ? Q.clientTop || 0 : Q.clientLeft || 0 : 0, Y = null != (L = null == x ? void 0 : x[y]) ? L : 0, U = I + K - Y, G = Ne(f ? ye(N, I + V - Y - X) : N, I, f ? ve(P, U) : P); A[y] = G, k[y] = G - I } if (a) { var J, Z = "x" === y ? zt : Vt, tt = "x" === y ? Rt : qt, et = A[w], it = "y" === w ? "height" : "width", nt = et + g[Z], st = et - g[tt], ot = -1 !== [zt, Vt].indexOf(_), rt = null != (J = null == x ? void 0 : x[w]) ? J : 0, at = ot ? nt : et - E[it] - T[it] - rt + O.altAxis, lt = ot ? et + E[it] + T[it] - rt - O.altAxis : st, ct = f && ot ? function (t, e, i) { var n = Ne(t, e, i); return n > i ? i : n }(at, et, lt) : Ne(f ? at : nt, et, f ? lt : st); A[w] = ct, k[w] = ct - et } e.modifiersData[n] = k } }, requiresIfExists: ["offset"] }; function di(t, e, i) { void 0 === i && (i = !1); var n, s, o = me(e), r = me(e) && function (t) { var e = t.getBoundingClientRect(), i = we(e.width) / t.offsetWidth || 1, n = we(e.height) / t.offsetHeight || 1; return 1 !== i || 1 !== n }(e), a = Le(e), l = Te(t, r, i), c = { scrollLeft: 0, scrollTop: 0 }, h = { x: 0, y: 0 }; return (o || !o && !i) && (("body" !== ue(e) || Ue(a)) && (c = (n = e) !== fe(n) && me(n) ? { scrollLeft: (s = n).scrollLeft, scrollTop: s.scrollTop } : Xe(n)), me(e) ? ((h = Te(e, !0)).x += e.clientLeft, h.y += e.clientTop) : a && (h.x = Ye(a))), { x: l.left + c.scrollLeft - h.x, y: l.top + c.scrollTop - h.y, width: l.width, height: l.height } } function ui(t) { var e = new Map, i = new Set, n = []; function s(t) { i.add(t.name), [].concat(t.requires || [], t.requiresIfExists || []).forEach((function (t) { if (!i.has(t)) { var n = e.get(t); n && s(n) } })), n.push(t) } return t.forEach((function (t) { e.set(t.name, t) })), t.forEach((function (t) { i.has(t.name) || s(t) })), n } var fi = { placement: "bottom", modifiers: [], strategy: "absolute" }; function pi() { for (var t = arguments.length, e = new Array(t), i = 0; i < t; i++)e[i] = arguments[i]; return !e.some((function (t) { return !(t && "function" == typeof t.getBoundingClientRect) })) } function mi(t) { void 0 === t && (t = {}); var e = t, i = e.defaultModifiers, n = void 0 === i ? [] : i, s = e.defaultOptions, o = void 0 === s ? fi : s; return function (t, e, i) { void 0 === i && (i = o); var s, r, a = { placement: "bottom", orderedModifiers: [], options: Object.assign({}, fi, o), modifiersData: {}, elements: { reference: t, popper: e }, attributes: {}, styles: {} }, l = [], c = !1, h = { state: a, setOptions: function (i) { var s = "function" == typeof i ? i(a.options) : i; d(), a.options = Object.assign({}, o, a.options, s), a.scrollParents = { reference: pe(t) ? Je(t) : t.contextElement ? Je(t.contextElement) : [], popper: Je(e) }; var r, c, u = function (t) { var e = ui(t); return de.reduce((function (t, i) { return t.concat(e.filter((function (t) { return t.phase === i }))) }), []) }((r = [].concat(n, a.options.modifiers), c = r.reduce((function (t, e) { var i = t[e.name]; return t[e.name] = i ? Object.assign({}, i, e, { options: Object.assign({}, i.options, e.options), data: Object.assign({}, i.data, e.data) }) : e, t }), {}), Object.keys(c).map((function (t) { return c[t] })))); return a.orderedModifiers = u.filter((function (t) { return t.enabled })), a.orderedModifiers.forEach((function (t) { var e = t.name, i = t.options, n = void 0 === i ? {} : i, s = t.effect; if ("function" == typeof s) { var o = s({ state: a, name: e, instance: h, options: n }); l.push(o || function () { }) } })), h.update() }, forceUpdate: function () { if (!c) { var t = a.elements, e = t.reference, i = t.popper; if (pi(e, i)) { a.rects = { reference: di(e, $e(i), "fixed" === a.options.strategy), popper: Ce(i) }, a.reset = !1, a.placement = a.options.placement, a.orderedModifiers.forEach((function (t) { return a.modifiersData[t.name] = Object.assign({}, t.data) })); for (var n = 0; n < a.orderedModifiers.length; n++)if (!0 !== a.reset) { var s = a.orderedModifiers[n], o = s.fn, r = s.options, l = void 0 === r ? {} : r, d = s.name; "function" == typeof o && (a = o({ state: a, options: l, name: d, instance: h }) || a) } else a.reset = !1, n = -1 } } }, update: (s = function () { return new Promise((function (t) { h.forceUpdate(), t(a) })) }, function () { return r || (r = new Promise((function (t) { Promise.resolve().then((function () { r = void 0, t(s()) })) }))), r }), destroy: function () { d(), c = !0 } }; if (!pi(t, e)) return h; function d() { l.forEach((function (t) { return t() })), l = [] } return h.setOptions(i).then((function (t) { !c && i.onFirstUpdate && i.onFirstUpdate(t) })), h } } var gi = mi(), _i = mi({ defaultModifiers: [Re, ci, Be, _e] }), bi = mi({ defaultModifiers: [Re, ci, Be, _e, li, si, hi, Me, ai] }); const vi = Object.freeze(Object.defineProperty({ __proto__: null, afterMain: ae, afterRead: se, afterWrite: he, applyStyles: _e, arrow: Me, auto: Kt, basePlacements: Qt, beforeMain: oe, beforeRead: ie, beforeWrite: le, bottom: Rt, clippingParents: Ut, computeStyles: Be, createPopper: bi, createPopperBase: gi, createPopperLite: _i, detectOverflow: ii, end: Yt, eventListeners: Re, flip: si, hide: ai, left: Vt, main: re, modifierPhases: de, offset: li, placements: ee, popper: Jt, popperGenerator: mi, popperOffsets: ci, preventOverflow: hi, read: ne, reference: Zt, right: qt, start: Xt, top: zt, variationPlacements: te, viewport: Gt, write: ce }, Symbol.toStringTag, { value: "Module" })), yi = "dropdown", wi = ".bs.dropdown", Ai = ".data-api", Ei = "ArrowUp", Ti = "ArrowDown", Ci = `hide${wi}`, Oi = `hidden${wi}`, xi = `show${wi}`, ki = `shown${wi}`, Li = `click${wi}${Ai}`, Si = `keydown${wi}${Ai}`, Di = `keyup${wi}${Ai}`, $i = "show", Ii = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)', Ni = `${Ii}.${$i}`, Pi = ".dropdown-menu", ji = p() ? "top-end" : "top-start", Mi = p() ? "top-start" : "top-end", Fi = p() ? "bottom-end" : "bottom-start", Hi = p() ? "bottom-start" : "bottom-end", Wi = p() ? "left-start" : "right-start", Bi = p() ? "right-start" : "left-start", zi = { autoClose: !0, boundary: "clippingParents", display: "dynamic", offset: [0, 2], popperConfig: null, reference: "toggle" }, Ri = { autoClose: "(boolean|string)", boundary: "(string|element)", display: "string", offset: "(array|string|function)", popperConfig: "(null|object|function)", reference: "(string|element|object)" }; class qi extends W { constructor(t, e) { super(t, e), this._popper = null, this._parent = this._element.parentNode, this._menu = z.next(this._element, Pi)[0] || z.prev(this._element, Pi)[0] || z.findOne(Pi, this._parent), this._inNavbar = this._detectNavbar() } static get Default() { return zi } static get DefaultType() { return Ri } static get NAME() { return yi } toggle() { return this._isShown() ? this.hide() : this.show() } show() { if (l(this._element) || this._isShown()) return; const t = { relatedTarget: this._element }; if (!N.trigger(this._element, xi, t).defaultPrevented) { if (this._createPopper(), "ontouchstart" in document.documentElement && !this._parent.closest(".navbar-nav")) for (const t of [].concat(...document.body.children)) N.on(t, "mouseover", h); this._element.focus(), this._element.setAttribute("aria-expanded", !0), this._menu.classList.add($i), this._element.classList.add($i), N.trigger(this._element, ki, t) } } hide() { if (l(this._element) || !this._isShown()) return; const t = { relatedTarget: this._element }; this._completeHide(t) } dispose() { this._popper && this._popper.destroy(), super.dispose() } update() { this._inNavbar = this._detectNavbar(), this._popper && this._popper.update() } _completeHide(t) { if (!N.trigger(this._element, Ci, t).defaultPrevented) { if ("ontouchstart" in document.documentElement) for (const t of [].concat(...document.body.children)) N.off(t, "mouseover", h); this._popper && this._popper.destroy(), this._menu.classList.remove($i), this._element.classList.remove($i), this._element.setAttribute("aria-expanded", "false"), F.removeDataAttribute(this._menu, "popper"), N.trigger(this._element, Oi, t) } } _getConfig(t) { if ("object" == typeof (t = super._getConfig(t)).reference && !o(t.reference) && "function" != typeof t.reference.getBoundingClientRect) throw new TypeError(`${yi.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`); return t } _createPopper() { if (void 0 === vi) throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)"); let t = this._element; "parent" === this._config.reference ? t = this._parent : o(this._config.reference) ? t = r(this._config.reference) : "object" == typeof this._config.reference && (t = this._config.reference); const e = this._getPopperConfig(); this._popper = bi(t, this._menu, e) } _isShown() { return this._menu.classList.contains($i) } _getPlacement() { const t = this._parent; if (t.classList.contains("dropend")) return Wi; if (t.classList.contains("dropstart")) return Bi; if (t.classList.contains("dropup-center")) return "top"; if (t.classList.contains("dropdown-center")) return "bottom"; const e = "end" === getComputedStyle(this._menu).getPropertyValue("--bs-position").trim(); return t.classList.contains("dropup") ? e ? Mi : ji : e ? Hi : Fi } _detectNavbar() { return null !== this._element.closest(".navbar") } _getOffset() { const { offset: t } = this._config; return "string" == typeof t ? t.split(",").map((t => Number.parseInt(t, 10))) : "function" == typeof t ? e => t(e, this._element) : t } _getPopperConfig() { const t = { placement: this._getPlacement(), modifiers: [{ name: "preventOverflow", options: { boundary: this._config.boundary } }, { name: "offset", options: { offset: this._getOffset() } }] }; return (this._inNavbar || "static" === this._config.display) && (F.setDataAttribute(this._menu, "popper", "static"), t.modifiers = [{ name: "applyStyles", enabled: !1 }]), { ...t, ...g(this._config.popperConfig, [t]) } } _selectMenuItem({ key: t, target: e }) { const i = z.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)", this._menu).filter((t => a(t))); i.length && b(i, e, t === Ti, !i.includes(e)).focus() } static jQueryInterface(t) { return this.each((function () { const e = qi.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t]) throw new TypeError(`No method named "${t}"`); e[t]() } })) } static clearMenus(t) { if (2 === t.button || "keyup" === t.type && "Tab" !== t.key) return; const e = z.find(Ni); for (const i of e) { const e = qi.getInstance(i); if (!e || !1 === e._config.autoClose) continue; const n = t.composedPath(), s = n.includes(e._menu); if (n.includes(e._element) || "inside" === e._config.autoClose && !s || "outside" === e._config.autoClose && s) continue; if (e._menu.contains(t.target) && ("keyup" === t.type && "Tab" === t.key || /input|select|option|textarea|form/i.test(t.target.tagName))) continue; const o = { relatedTarget: e._element }; "click" === t.type && (o.clickEvent = t), e._completeHide(o) } } static dataApiKeydownHandler(t) { const e = /input|textarea/i.test(t.target.tagName), i = "Escape" === t.key, n = [Ei, Ti].includes(t.key); if (!n && !i) return; if (e && !i) return; t.preventDefault(); const s = this.matches(Ii) ? this : z.prev(this, Ii)[0] || z.next(this, Ii)[0] || z.findOne(Ii, t.delegateTarget.parentNode), o = qi.getOrCreateInstance(s); if (n) return t.stopPropagation(), o.show(), void o._selectMenuItem(t); o._isShown() && (t.stopPropagation(), o.hide(), s.focus()) } } N.on(document, Si, Ii, qi.dataApiKeydownHandler), N.on(document, Si, Pi, qi.dataApiKeydownHandler), N.on(document, Li, qi.clearMenus), N.on(document, Di, qi.clearMenus), N.on(document, Li, Ii, (function (t) { t.preventDefault(), qi.getOrCreateInstance(this).toggle() })), m(qi); const Vi = "backdrop", Ki = "show", Qi = `mousedown.bs.${Vi}`, Xi = { className: "modal-backdrop", clickCallback: null, isAnimated: !1, isVisible: !0, rootElement: "body" }, Yi = { className: "string", clickCallback: "(function|null)", isAnimated: "boolean", isVisible: "boolean", rootElement: "(element|string)" }; class Ui extends H { constructor(t) { super(), this._config = this._getConfig(t), this._isAppended = !1, this._element = null } static get Default() { return Xi } static get DefaultType() { return Yi } static get NAME() { return Vi } show(t) { if (!this._config.isVisible) return void g(t); this._append(); const e = this._getElement(); this._config.isAnimated && d(e), e.classList.add(Ki), this._emulateAnimation((() => { g(t) })) } hide(t) { this._config.isVisible ? (this._getElement().classList.remove(Ki), this._emulateAnimation((() => { this.dispose(), g(t) }))) : g(t) } dispose() { this._isAppended && (N.off(this._element, Qi), this._element.remove(), this._isAppended = !1) } _getElement() { if (!this._element) { const t = document.createElement("div"); t.className = this._config.className, this._config.isAnimated && t.classList.add("fade"), this._element = t } return this._element } _configAfterMerge(t) { return t.rootElement = r(t.rootElement), t } _append() { if (this._isAppended) return; const t = this._getElement(); this._config.rootElement.append(t), N.on(t, Qi, (() => { g(this._config.clickCallback) })), this._isAppended = !0 } _emulateAnimation(t) { _(t, this._getElement(), this._config.isAnimated) } } const Gi = ".bs.focustrap", Ji = `focusin${Gi}`, Zi = `keydown.tab${Gi}`, tn = "backward", en = { autofocus: !0, trapElement: null }, nn = { autofocus: "boolean", trapElement: "element" }; class sn extends H { constructor(t) { super(), this._config = this._getConfig(t), this._isActive = !1, this._lastTabNavDirection = null } static get Default() { return en } static get DefaultType() { return nn } static get NAME() { return "focustrap" } activate() { this._isActive || (this._config.autofocus && this._config.trapElement.focus(), N.off(document, Gi), N.on(document, Ji, (t => this._handleFocusin(t))), N.on(document, Zi, (t => this._handleKeydown(t))), this._isActive = !0) } deactivate() { this._isActive && (this._isActive = !1, N.off(document, Gi)) } _handleFocusin(t) { const { trapElement: e } = this._config; if (t.target === document || t.target === e || e.contains(t.target)) return; const i = z.focusableChildren(e); 0 === i.length ? e.focus() : this._lastTabNavDirection === tn ? i[i.length - 1].focus() : i[0].focus() } _handleKeydown(t) { "Tab" === t.key && (this._lastTabNavDirection = t.shiftKey ? tn : "forward") } } const on = ".fixed-top, .fixed-bottom, .is-fixed, .sticky-top", rn = ".sticky-top", an = "padding-right", ln = "margin-right"; class cn { constructor() { this._element = document.body } getWidth() { const t = document.documentElement.clientWidth; return Math.abs(window.innerWidth - t) } hide() { const t = this.getWidth(); this._disableOverFlow(), this._setElementAttributes(this._element, an, (e => e + t)), this._setElementAttributes(on, an, (e => e + t)), this._setElementAttributes(rn, ln, (e => e - t)) } reset() { this._resetElementAttributes(this._element, "overflow"), this._resetElementAttributes(this._element, an), this._resetElementAttributes(on, an), this._resetElementAttributes(rn, ln) } isOverflowing() { return this.getWidth() > 0 } _disableOverFlow() { this._saveInitialAttribute(this._element, "overflow"), this._element.style.overflow = "hidden" } _setElementAttributes(t, e, i) { const n = this.getWidth(); this._applyManipulationCallback(t, (t => { if (t !== this._element && window.innerWidth > t.clientWidth + n) return; this._saveInitialAttribute(t, e); const s = window.getComputedStyle(t).getPropertyValue(e); t.style.setProperty(e, `${i(Number.parseFloat(s))}px`) })) } _saveInitialAttribute(t, e) { const i = t.style.getPropertyValue(e); i && F.setDataAttribute(t, e, i) } _resetElementAttributes(t, e) { this._applyManipulationCallback(t, (t => { const i = F.getDataAttribute(t, e); null !== i ? (F.removeDataAttribute(t, e), t.style.setProperty(e, i)) : t.style.removeProperty(e) })) } _applyManipulationCallback(t, e) { if (o(t)) e(t); else for (const i of z.find(t, this._element)) e(i) } } const hn = ".bs.modal", dn = `hide${hn}`, un = `hidePrevented${hn}`, fn = `hidden${hn}`, pn = `show${hn}`, mn = `shown${hn}`, gn = `resize${hn}`, _n = `click.dismiss${hn}`, bn = `mousedown.dismiss${hn}`, vn = `keydown.dismiss${hn}`, yn = `click${hn}.data-api`, wn = "modal-open", An = "show", En = "modal-static", Tn = { backdrop: !0, focus: !0, keyboard: !0 }, Cn = { backdrop: "(boolean|string)", focus: "boolean", keyboard: "boolean" }; class On extends W { constructor(t, e) { super(t, e), this._dialog = z.findOne(".modal-dialog", this._element), this._backdrop = this._initializeBackDrop(), this._focustrap = this._initializeFocusTrap(), this._isShown = !1, this._isTransitioning = !1, this._scrollBar = new cn, this._addEventListeners() } static get Default() { return Tn } static get DefaultType() { return Cn } static get NAME() { return "modal" } toggle(t) { return this._isShown ? this.hide() : this.show(t) } show(t) { this._isShown || this._isTransitioning || N.trigger(this._element, pn, { relatedTarget: t }).defaultPrevented || (this._isShown = !0, this._isTransitioning = !0, this._scrollBar.hide(), document.body.classList.add(wn), this._adjustDialog(), this._backdrop.show((() => this._showElement(t)))) } hide() { this._isShown && !this._isTransitioning && (N.trigger(this._element, dn).defaultPrevented || (this._isShown = !1, this._isTransitioning = !0, this._focustrap.deactivate(), this._element.classList.remove(An), this._queueCallback((() => this._hideModal()), this._element, this._isAnimated()))) } dispose() { N.off(window, hn), N.off(this._dialog, hn), this._backdrop.dispose(), this._focustrap.deactivate(), super.dispose() } handleUpdate() { this._adjustDialog() } _initializeBackDrop() { return new Ui({ isVisible: Boolean(this._config.backdrop), isAnimated: this._isAnimated() }) } _initializeFocusTrap() { return new sn({ trapElement: this._element }) } _showElement(t) { document.body.contains(this._element) || document.body.append(this._element), this._element.style.display = "block", this._element.removeAttribute("aria-hidden"), this._element.setAttribute("aria-modal", !0), this._element.setAttribute("role", "dialog"), this._element.scrollTop = 0; const e = z.findOne(".modal-body", this._dialog); e && (e.scrollTop = 0), d(this._element), this._element.classList.add(An), this._queueCallback((() => { this._config.focus && this._focustrap.activate(), this._isTransitioning = !1, N.trigger(this._element, mn, { relatedTarget: t }) }), this._dialog, this._isAnimated()) } _addEventListeners() { N.on(this._element, vn, (t => { "Escape" === t.key && (this._config.keyboard ? this.hide() : this._triggerBackdropTransition()) })), N.on(window, gn, (() => { this._isShown && !this._isTransitioning && this._adjustDialog() })), N.on(this._element, bn, (t => { N.one(this._element, _n, (e => { this._element === t.target && this._element === e.target && ("static" !== this._config.backdrop ? this._config.backdrop && this.hide() : this._triggerBackdropTransition()) })) })) } _hideModal() { this._element.style.display = "none", this._element.setAttribute("aria-hidden", !0), this._element.removeAttribute("aria-modal"), this._element.removeAttribute("role"), this._isTransitioning = !1, this._backdrop.hide((() => { document.body.classList.remove(wn), this._resetAdjustments(), this._scrollBar.reset(), N.trigger(this._element, fn) })) } _isAnimated() { return this._element.classList.contains("fade") } _triggerBackdropTransition() { if (N.trigger(this._element, un).defaultPrevented) return; const t = this._element.scrollHeight > document.documentElement.clientHeight, e = this._element.style.overflowY; "hidden" === e || this._element.classList.contains(En) || (t || (this._element.style.overflowY = "hidden"), this._element.classList.add(En), this._queueCallback((() => { this._element.classList.remove(En), this._queueCallback((() => { this._element.style.overflowY = e }), this._dialog) }), this._dialog), this._element.focus()) } _adjustDialog() { const t = this._element.scrollHeight > document.documentElement.clientHeight, e = this._scrollBar.getWidth(), i = e > 0; if (i && !t) { const t = p() ? "paddingLeft" : "paddingRight"; this._element.style[t] = `${e}px` } if (!i && t) { const t = p() ? "paddingRight" : "paddingLeft"; this._element.style[t] = `${e}px` } } _resetAdjustments() { this._element.style.paddingLeft = "", this._element.style.paddingRight = "" } static jQueryInterface(t, e) { return this.each((function () { const i = On.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === i[t]) throw new TypeError(`No method named "${t}"`); i[t](e) } })) } } N.on(document, yn, '[data-bs-toggle="modal"]', (function (t) { const e = z.getElementFromSelector(this);["A", "AREA"].includes(this.tagName) && t.preventDefault(), N.one(e, pn, (t => { t.defaultPrevented || N.one(e, fn, (() => { a(this) && this.focus() })) })); const i = z.findOne(".modal.show"); i && On.getInstance(i).hide(), On.getOrCreateInstance(e).toggle(this) })), R(On), m(On); const xn = ".bs.offcanvas", kn = ".data-api", Ln = `load${xn}${kn}`, Sn = "show", Dn = "showing", $n = "hiding", In = ".offcanvas.show", Nn = `show${xn}`, Pn = `shown${xn}`, jn = `hide${xn}`, Mn = `hidePrevented${xn}`, Fn = `hidden${xn}`, Hn = `resize${xn}`, Wn = `click${xn}${kn}`, Bn = `keydown.dismiss${xn}`, zn = { backdrop: !0, keyboard: !0, scroll: !1 }, Rn = { backdrop: "(boolean|string)", keyboard: "boolean", scroll: "boolean" }; class qn extends W { constructor(t, e) { super(t, e), this._isShown = !1, this._backdrop = this._initializeBackDrop(), this._focustrap = this._initializeFocusTrap(), this._addEventListeners() } static get Default() { return zn } static get DefaultType() { return Rn } static get NAME() { return "offcanvas" } toggle(t) { return this._isShown ? this.hide() : this.show(t) } show(t) { this._isShown || N.trigger(this._element, Nn, { relatedTarget: t }).defaultPrevented || (this._isShown = !0, this._backdrop.show(), this._config.scroll || (new cn).hide(), this._element.setAttribute("aria-modal", !0), this._element.setAttribute("role", "dialog"), this._element.classList.add(Dn), this._queueCallback((() => { this._config.scroll && !this._config.backdrop || this._focustrap.activate(), this._element.classList.add(Sn), this._element.classList.remove(Dn), N.trigger(this._element, Pn, { relatedTarget: t }) }), this._element, !0)) } hide() { this._isShown && (N.trigger(this._element, jn).defaultPrevented || (this._focustrap.deactivate(), this._element.blur(), this._isShown = !1, this._element.classList.add($n), this._backdrop.hide(), this._queueCallback((() => { this._element.classList.remove(Sn, $n), this._element.removeAttribute("aria-modal"), this._element.removeAttribute("role"), this._config.scroll || (new cn).reset(), N.trigger(this._element, Fn) }), this._element, !0))) } dispose() { this._backdrop.dispose(), this._focustrap.deactivate(), super.dispose() } _initializeBackDrop() { const t = Boolean(this._config.backdrop); return new Ui({ className: "offcanvas-backdrop", isVisible: t, isAnimated: !0, rootElement: this._element.parentNode, clickCallback: t ? () => { "static" !== this._config.backdrop ? this.hide() : N.trigger(this._element, Mn) } : null }) } _initializeFocusTrap() { return new sn({ trapElement: this._element }) } _addEventListeners() { N.on(this._element, Bn, (t => { "Escape" === t.key && (this._config.keyboard ? this.hide() : N.trigger(this._element, Mn)) })) } static jQueryInterface(t) { return this.each((function () { const e = qn.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) throw new TypeError(`No method named "${t}"`); e[t](this) } })) } } N.on(document, Wn, '[data-bs-toggle="offcanvas"]', (function (t) { const e = z.getElementFromSelector(this); if (["A", "AREA"].includes(this.tagName) && t.preventDefault(), l(this)) return; N.one(e, Fn, (() => { a(this) && this.focus() })); const i = z.findOne(In); i && i !== e && qn.getInstance(i).hide(), qn.getOrCreateInstance(e).toggle(this) })), N.on(window, Ln, (() => { for (const t of z.find(In)) qn.getOrCreateInstance(t).show() })), N.on(window, Hn, (() => { for (const t of z.find("[aria-modal][class*=show][class*=offcanvas-]")) "fixed" !== getComputedStyle(t).position && qn.getOrCreateInstance(t).hide() })), R(qn), m(qn); const Vn = { "*": ["class", "dir", "id", "lang", "role", /^aria-[\w-]*$/i], a: ["target", "href", "title", "rel"], area: [], b: [], br: [], col: [], code: [], dd: [], div: [], dl: [], dt: [], em: [], hr: [], h1: [], h2: [], h3: [], h4: [], h5: [], h6: [], i: [], img: ["src", "srcset", "alt", "title", "width", "height"], li: [], ol: [], p: [], pre: [], s: [], small: [], span: [], sub: [], sup: [], strong: [], u: [], ul: [] }, Kn = new Set(["background", "cite", "href", "itemtype", "longdesc", "poster", "src", "xlink:href"]), Qn = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i, Xn = (t, e) => { const i = t.nodeName.toLowerCase(); return e.includes(i) ? !Kn.has(i) || Boolean(Qn.test(t.nodeValue)) : e.filter((t => t instanceof RegExp)).some((t => t.test(i))) }, Yn = { allowList: Vn, content: {}, extraClass: "", html: !1, sanitize: !0, sanitizeFn: null, template: "
" }, Un = { allowList: "object", content: "object", extraClass: "(string|function)", html: "boolean", sanitize: "boolean", sanitizeFn: "(null|function)", template: "string" }, Gn = { entry: "(string|element|function|null)", selector: "(string|element)" }; class Jn extends H { constructor(t) { super(), this._config = this._getConfig(t) } static get Default() { return Yn } static get DefaultType() { return Un } static get NAME() { return "TemplateFactory" } getContent() { return Object.values(this._config.content).map((t => this._resolvePossibleFunction(t))).filter(Boolean) } hasContent() { return this.getContent().length > 0 } changeContent(t) { return this._checkContent(t), this._config.content = { ...this._config.content, ...t }, this } toHtml() { const t = document.createElement("div"); t.innerHTML = this._maybeSanitize(this._config.template); for (const [e, i] of Object.entries(this._config.content)) this._setContent(t, i, e); const e = t.children[0], i = this._resolvePossibleFunction(this._config.extraClass); return i && e.classList.add(...i.split(" ")), e } _typeCheckConfig(t) { super._typeCheckConfig(t), this._checkContent(t.content) } _checkContent(t) { for (const [e, i] of Object.entries(t)) super._typeCheckConfig({ selector: e, entry: i }, Gn) } _setContent(t, e, i) { const n = z.findOne(i, t); n && ((e = this._resolvePossibleFunction(e)) ? o(e) ? this._putElementInTemplate(r(e), n) : this._config.html ? n.innerHTML = this._maybeSanitize(e) : n.textContent = e : n.remove()) } _maybeSanitize(t) { return this._config.sanitize ? function (t, e, i) { if (!t.length) return t; if (i && "function" == typeof i) return i(t); const n = (new window.DOMParser).parseFromString(t, "text/html"), s = [].concat(...n.body.querySelectorAll("*")); for (const t of s) { const i = t.nodeName.toLowerCase(); if (!Object.keys(e).includes(i)) { t.remove(); continue } const n = [].concat(...t.attributes), s = [].concat(e["*"] || [], e[i] || []); for (const e of n) Xn(e, s) || t.removeAttribute(e.nodeName) } return n.body.innerHTML }(t, this._config.allowList, this._config.sanitizeFn) : t } _resolvePossibleFunction(t) { return g(t, [this]) } _putElementInTemplate(t, e) { if (this._config.html) return e.innerHTML = "", void e.append(t); e.textContent = t.textContent } } const Zn = new Set(["sanitize", "allowList", "sanitizeFn"]), ts = "fade", es = "show", is = ".modal", ns = "hide.bs.modal", ss = "hover", os = "focus", rs = { AUTO: "auto", TOP: "top", RIGHT: p() ? "left" : "right", BOTTOM: "bottom", LEFT: p() ? "right" : "left" }, as = { allowList: Vn, animation: !0, boundary: "clippingParents", container: !1, customClass: "", delay: 0, fallbackPlacements: ["top", "right", "bottom", "left"], html: !1, offset: [0, 6], placement: "top", popperConfig: null, sanitize: !0, sanitizeFn: null, selector: !1, template: '', title: "", trigger: "hover focus" }, ls = { allowList: "object", animation: "boolean", boundary: "(string|element)", container: "(string|element|boolean)", customClass: "(string|function)", delay: "(number|object)", fallbackPlacements: "array", html: "boolean", offset: "(array|string|function)", placement: "(string|function)", popperConfig: "(null|object|function)", sanitize: "boolean", sanitizeFn: "(null|function)", selector: "(string|boolean)", template: "string", title: "(string|element|function)", trigger: "string" }; class cs extends W { constructor(t, e) { if (void 0 === vi) throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)"); super(t, e), this._isEnabled = !0, this._timeout = 0, this._isHovered = null, this._activeTrigger = {}, this._popper = null, this._templateFactory = null, this._newContent = null, this.tip = null, this._setListeners(), this._config.selector || this._fixTitle() } static get Default() { return as } static get DefaultType() { return ls } static get NAME() { return "tooltip" } enable() { this._isEnabled = !0 } disable() { this._isEnabled = !1 } toggleEnabled() { this._isEnabled = !this._isEnabled } toggle() { this._isEnabled && (this._activeTrigger.click = !this._activeTrigger.click, this._isShown() ? this._leave() : this._enter()) } dispose() { clearTimeout(this._timeout), N.off(this._element.closest(is), ns, this._hideModalHandler), this._element.getAttribute("data-bs-original-title") && this._element.setAttribute("title", this._element.getAttribute("data-bs-original-title")), this._disposePopper(), super.dispose() } show() { if ("none" === this._element.style.display) throw new Error("Please use show on visible elements"); if (!this._isWithContent() || !this._isEnabled) return; const t = N.trigger(this._element, this.constructor.eventName("show")), e = (c(this._element) || this._element.ownerDocument.documentElement).contains(this._element); if (t.defaultPrevented || !e) return; this._disposePopper(); const i = this._getTipElement(); this._element.setAttribute("aria-describedby", i.getAttribute("id")); const { container: n } = this._config; if (this._element.ownerDocument.documentElement.contains(this.tip) || (n.append(i), N.trigger(this._element, this.constructor.eventName("inserted"))), this._popper = this._createPopper(i), i.classList.add(es), "ontouchstart" in document.documentElement) for (const t of [].concat(...document.body.children)) N.on(t, "mouseover", h); this._queueCallback((() => { N.trigger(this._element, this.constructor.eventName("shown")), !1 === this._isHovered && this._leave(), this._isHovered = !1 }), this.tip, this._isAnimated()) } hide() { if (this._isShown() && !N.trigger(this._element, this.constructor.eventName("hide")).defaultPrevented) { if (this._getTipElement().classList.remove(es), "ontouchstart" in document.documentElement) for (const t of [].concat(...document.body.children)) N.off(t, "mouseover", h); this._activeTrigger.click = !1, this._activeTrigger[os] = !1, this._activeTrigger[ss] = !1, this._isHovered = null, this._queueCallback((() => { this._isWithActiveTrigger() || (this._isHovered || this._disposePopper(), this._element.removeAttribute("aria-describedby"), N.trigger(this._element, this.constructor.eventName("hidden"))) }), this.tip, this._isAnimated()) } } update() { this._popper && this._popper.update() } _isWithContent() { return Boolean(this._getTitle()) } _getTipElement() { return this.tip || (this.tip = this._createTipElement(this._newContent || this._getContentForTemplate())), this.tip } _createTipElement(t) { const e = this._getTemplateFactory(t).toHtml(); if (!e) return null; e.classList.remove(ts, es), e.classList.add(`bs-${this.constructor.NAME}-auto`); const i = (t => { do { t += Math.floor(1e6 * Math.random()) } while (document.getElementById(t)); return t })(this.constructor.NAME).toString(); return e.setAttribute("id", i), this._isAnimated() && e.classList.add(ts), e } setContent(t) { this._newContent = t, this._isShown() && (this._disposePopper(), this.show()) } _getTemplateFactory(t) { return this._templateFactory ? this._templateFactory.changeContent(t) : this._templateFactory = new Jn({ ...this._config, content: t, extraClass: this._resolvePossibleFunction(this._config.customClass) }), this._templateFactory } _getContentForTemplate() { return { ".tooltip-inner": this._getTitle() } } _getTitle() { return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute("data-bs-original-title") } _initializeOnDelegatedTarget(t) { return this.constructor.getOrCreateInstance(t.delegateTarget, this._getDelegateConfig()) } _isAnimated() { return this._config.animation || this.tip && this.tip.classList.contains(ts) } _isShown() { return this.tip && this.tip.classList.contains(es) } _createPopper(t) { const e = g(this._config.placement, [this, t, this._element]), i = rs[e.toUpperCase()]; return bi(this._element, t, this._getPopperConfig(i)) } _getOffset() { const { offset: t } = this._config; return "string" == typeof t ? t.split(",").map((t => Number.parseInt(t, 10))) : "function" == typeof t ? e => t(e, this._element) : t } _resolvePossibleFunction(t) { return g(t, [this._element]) } _getPopperConfig(t) { const e = { placement: t, modifiers: [{ name: "flip", options: { fallbackPlacements: this._config.fallbackPlacements } }, { name: "offset", options: { offset: this._getOffset() } }, { name: "preventOverflow", options: { boundary: this._config.boundary } }, { name: "arrow", options: { element: `.${this.constructor.NAME}-arrow` } }, { name: "preSetPlacement", enabled: !0, phase: "beforeMain", fn: t => { this._getTipElement().setAttribute("data-popper-placement", t.state.placement) } }] }; return { ...e, ...g(this._config.popperConfig, [e]) } } _setListeners() { const t = this._config.trigger.split(" "); for (const e of t) if ("click" === e) N.on(this._element, this.constructor.eventName("click"), this._config.selector, (t => { this._initializeOnDelegatedTarget(t).toggle() })); else if ("manual" !== e) { const t = e === ss ? this.constructor.eventName("mouseenter") : this.constructor.eventName("focusin"), i = e === ss ? this.constructor.eventName("mouseleave") : this.constructor.eventName("focusout"); N.on(this._element, t, this._config.selector, (t => { const e = this._initializeOnDelegatedTarget(t); e._activeTrigger["focusin" === t.type ? os : ss] = !0, e._enter() })), N.on(this._element, i, this._config.selector, (t => { const e = this._initializeOnDelegatedTarget(t); e._activeTrigger["focusout" === t.type ? os : ss] = e._element.contains(t.relatedTarget), e._leave() })) } this._hideModalHandler = () => { this._element && this.hide() }, N.on(this._element.closest(is), ns, this._hideModalHandler) } _fixTitle() { const t = this._element.getAttribute("title"); t && (this._element.getAttribute("aria-label") || this._element.textContent.trim() || this._element.setAttribute("aria-label", t), this._element.setAttribute("data-bs-original-title", t), this._element.removeAttribute("title")) } _enter() { this._isShown() || this._isHovered ? this._isHovered = !0 : (this._isHovered = !0, this._setTimeout((() => { this._isHovered && this.show() }), this._config.delay.show)) } _leave() { this._isWithActiveTrigger() || (this._isHovered = !1, this._setTimeout((() => { this._isHovered || this.hide() }), this._config.delay.hide)) } _setTimeout(t, e) { clearTimeout(this._timeout), this._timeout = setTimeout(t, e) } _isWithActiveTrigger() { return Object.values(this._activeTrigger).includes(!0) } _getConfig(t) { const e = F.getDataAttributes(this._element); for (const t of Object.keys(e)) Zn.has(t) && delete e[t]; return t = { ...e, ..."object" == typeof t && t ? t : {} }, t = this._mergeConfigObj(t), t = this._configAfterMerge(t), this._typeCheckConfig(t), t } _configAfterMerge(t) { return t.container = !1 === t.container ? document.body : r(t.container), "number" == typeof t.delay && (t.delay = { show: t.delay, hide: t.delay }), "number" == typeof t.title && (t.title = t.title.toString()), "number" == typeof t.content && (t.content = t.content.toString()), t } _getDelegateConfig() { const t = {}; for (const [e, i] of Object.entries(this._config)) this.constructor.Default[e] !== i && (t[e] = i); return t.selector = !1, t.trigger = "manual", t } _disposePopper() { this._popper && (this._popper.destroy(), this._popper = null), this.tip && (this.tip.remove(), this.tip = null) } static jQueryInterface(t) { return this.each((function () { const e = cs.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t]) throw new TypeError(`No method named "${t}"`); e[t]() } })) } } m(cs); const hs = { ...cs.Default, content: "", offset: [0, 8], placement: "right", template: '', trigger: "click" }, ds = { ...cs.DefaultType, content: "(null|string|element|function)" }; class us extends cs { static get Default() { return hs } static get DefaultType() { return ds } static get NAME() { return "popover" } _isWithContent() { return this._getTitle() || this._getContent() } _getContentForTemplate() { return { ".popover-header": this._getTitle(), ".popover-body": this._getContent() } } _getContent() { return this._resolvePossibleFunction(this._config.content) } static jQueryInterface(t) { return this.each((function () { const e = us.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t]) throw new TypeError(`No method named "${t}"`); e[t]() } })) } } m(us); const fs = ".bs.scrollspy", ps = `activate${fs}`, ms = `click${fs}`, gs = `load${fs}.data-api`, _s = "active", bs = "[href]", vs = ".nav-link", ys = `${vs}, .nav-item > ${vs}, .list-group-item`, ws = { offset: null, rootMargin: "0px 0px -25%", smoothScroll: !1, target: null, threshold: [.1, .5, 1] }, As = { offset: "(number|null)", rootMargin: "string", smoothScroll: "boolean", target: "element", threshold: "array" }; class Es extends W { constructor(t, e) { super(t, e), this._targetLinks = new Map, this._observableSections = new Map, this._rootElement = "visible" === getComputedStyle(this._element).overflowY ? null : this._element, this._activeTarget = null, this._observer = null, this._previousScrollData = { visibleEntryTop: 0, parentScrollTop: 0 }, this.refresh() } static get Default() { return ws } static get DefaultType() { return As } static get NAME() { return "scrollspy" } refresh() { this._initializeTargetsAndObservables(), this._maybeEnableSmoothScroll(), this._observer ? this._observer.disconnect() : this._observer = this._getNewObserver(); for (const t of this._observableSections.values()) this._observer.observe(t) } dispose() { this._observer.disconnect(), super.dispose() } _configAfterMerge(t) { return t.target = r(t.target) || document.body, t.rootMargin = t.offset ? `${t.offset}px 0px -30%` : t.rootMargin, "string" == typeof t.threshold && (t.threshold = t.threshold.split(",").map((t => Number.parseFloat(t)))), t } _maybeEnableSmoothScroll() { this._config.smoothScroll && (N.off(this._config.target, ms), N.on(this._config.target, ms, bs, (t => { const e = this._observableSections.get(t.target.hash); if (e) { t.preventDefault(); const i = this._rootElement || window, n = e.offsetTop - this._element.offsetTop; if (i.scrollTo) return void i.scrollTo({ top: n, behavior: "smooth" }); i.scrollTop = n } }))) } _getNewObserver() { const t = { root: this._rootElement, threshold: this._config.threshold, rootMargin: this._config.rootMargin }; return new IntersectionObserver((t => this._observerCallback(t)), t) } _observerCallback(t) { const e = t => this._targetLinks.get(`#${t.target.id}`), i = t => { this._previousScrollData.visibleEntryTop = t.target.offsetTop, this._process(e(t)) }, n = (this._rootElement || document.documentElement).scrollTop, s = n >= this._previousScrollData.parentScrollTop; this._previousScrollData.parentScrollTop = n; for (const o of t) { if (!o.isIntersecting) { this._activeTarget = null, this._clearActiveClass(e(o)); continue } const t = o.target.offsetTop >= this._previousScrollData.visibleEntryTop; if (s && t) { if (i(o), !n) return } else s || t || i(o) } } _initializeTargetsAndObservables() { this._targetLinks = new Map, this._observableSections = new Map; const t = z.find(bs, this._config.target); for (const e of t) { if (!e.hash || l(e)) continue; const t = z.findOne(decodeURI(e.hash), this._element); a(t) && (this._targetLinks.set(decodeURI(e.hash), e), this._observableSections.set(e.hash, t)) } } _process(t) { this._activeTarget !== t && (this._clearActiveClass(this._config.target), this._activeTarget = t, t.classList.add(_s), this._activateParents(t), N.trigger(this._element, ps, { relatedTarget: t })) } _activateParents(t) { if (t.classList.contains("dropdown-item")) z.findOne(".dropdown-toggle", t.closest(".dropdown")).classList.add(_s); else for (const e of z.parents(t, ".nav, .list-group")) for (const t of z.prev(e, ys)) t.classList.add(_s) } _clearActiveClass(t) { t.classList.remove(_s); const e = z.find(`${bs}.${_s}`, t); for (const t of e) t.classList.remove(_s) } static jQueryInterface(t) { return this.each((function () { const e = Es.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) throw new TypeError(`No method named "${t}"`); e[t]() } })) } } N.on(window, gs, (() => { for (const t of z.find('[data-bs-spy="scroll"]')) Es.getOrCreateInstance(t) })), m(Es); const Ts = ".bs.tab", Cs = `hide${Ts}`, Os = `hidden${Ts}`, xs = `show${Ts}`, ks = `shown${Ts}`, Ls = `click${Ts}`, Ss = `keydown${Ts}`, Ds = `load${Ts}`, $s = "ArrowLeft", Is = "ArrowRight", Ns = "ArrowUp", Ps = "ArrowDown", js = "Home", Ms = "End", Fs = "active", Hs = "fade", Ws = "show", Bs = ".dropdown-toggle", zs = `:not(${Bs})`, Rs = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]', qs = `.nav-link${zs}, .list-group-item${zs}, [role="tab"]${zs}, ${Rs}`, Vs = `.${Fs}[data-bs-toggle="tab"], .${Fs}[data-bs-toggle="pill"], .${Fs}[data-bs-toggle="list"]`; class Ks extends W { constructor(t) { super(t), this._parent = this._element.closest('.list-group, .nav, [role="tablist"]'), this._parent && (this._setInitialAttributes(this._parent, this._getChildren()), N.on(this._element, Ss, (t => this._keydown(t)))) } static get NAME() { return "tab" } show() { const t = this._element; if (this._elemIsActive(t)) return; const e = this._getActiveElem(), i = e ? N.trigger(e, Cs, { relatedTarget: t }) : null; N.trigger(t, xs, { relatedTarget: e }).defaultPrevented || i && i.defaultPrevented || (this._deactivate(e, t), this._activate(t, e)) } _activate(t, e) { t && (t.classList.add(Fs), this._activate(z.getElementFromSelector(t)), this._queueCallback((() => { "tab" === t.getAttribute("role") ? (t.removeAttribute("tabindex"), t.setAttribute("aria-selected", !0), this._toggleDropDown(t, !0), N.trigger(t, ks, { relatedTarget: e })) : t.classList.add(Ws) }), t, t.classList.contains(Hs))) } _deactivate(t, e) { t && (t.classList.remove(Fs), t.blur(), this._deactivate(z.getElementFromSelector(t)), this._queueCallback((() => { "tab" === t.getAttribute("role") ? (t.setAttribute("aria-selected", !1), t.setAttribute("tabindex", "-1"), this._toggleDropDown(t, !1), N.trigger(t, Os, { relatedTarget: e })) : t.classList.remove(Ws) }), t, t.classList.contains(Hs))) } _keydown(t) { if (![$s, Is, Ns, Ps, js, Ms].includes(t.key)) return; t.stopPropagation(), t.preventDefault(); const e = this._getChildren().filter((t => !l(t))); let i; if ([js, Ms].includes(t.key)) i = e[t.key === js ? 0 : e.length - 1]; else { const n = [Is, Ps].includes(t.key); i = b(e, t.target, n, !0) } i && (i.focus({ preventScroll: !0 }), Ks.getOrCreateInstance(i).show()) } _getChildren() { return z.find(qs, this._parent) } _getActiveElem() { return this._getChildren().find((t => this._elemIsActive(t))) || null } _setInitialAttributes(t, e) { this._setAttributeIfNotExists(t, "role", "tablist"); for (const t of e) this._setInitialAttributesOnChild(t) } _setInitialAttributesOnChild(t) { t = this._getInnerElement(t); const e = this._elemIsActive(t), i = this._getOuterElement(t); t.setAttribute("aria-selected", e), i !== t && this._setAttributeIfNotExists(i, "role", "presentation"), e || t.setAttribute("tabindex", "-1"), this._setAttributeIfNotExists(t, "role", "tab"), this._setInitialAttributesOnTargetPanel(t) } _setInitialAttributesOnTargetPanel(t) { const e = z.getElementFromSelector(t); e && (this._setAttributeIfNotExists(e, "role", "tabpanel"), t.id && this._setAttributeIfNotExists(e, "aria-labelledby", `${t.id}`)) } _toggleDropDown(t, e) { const i = this._getOuterElement(t); if (!i.classList.contains("dropdown")) return; const n = (t, n) => { const s = z.findOne(t, i); s && s.classList.toggle(n, e) }; n(Bs, Fs), n(".dropdown-menu", Ws), i.setAttribute("aria-expanded", e) } _setAttributeIfNotExists(t, e, i) { t.hasAttribute(e) || t.setAttribute(e, i) } _elemIsActive(t) { return t.classList.contains(Fs) } _getInnerElement(t) { return t.matches(qs) ? t : z.findOne(qs, t) } _getOuterElement(t) { return t.closest(".nav-item, .list-group-item") || t } static jQueryInterface(t) { return this.each((function () { const e = Ks.getOrCreateInstance(this); if ("string" == typeof t) { if (void 0 === e[t] || t.startsWith("_") || "constructor" === t) throw new TypeError(`No method named "${t}"`); e[t]() } })) } } N.on(document, Ls, Rs, (function (t) { ["A", "AREA"].includes(this.tagName) && t.preventDefault(), l(this) || Ks.getOrCreateInstance(this).show() })), N.on(window, Ds, (() => { for (const t of z.find(Vs)) Ks.getOrCreateInstance(t) })), m(Ks); const Qs = ".bs.toast", Xs = `mouseover${Qs}`, Ys = `mouseout${Qs}`, Us = `focusin${Qs}`, Gs = `focusout${Qs}`, Js = `hide${Qs}`, Zs = `hidden${Qs}`, to = `show${Qs}`, eo = `shown${Qs}`, io = "hide", no = "show", so = "showing", oo = { animation: "boolean", autohide: "boolean", delay: "number" }, ro = { animation: !0, autohide: !0, delay: 5e3 }; class ao extends W { constructor(t, e) { super(t, e), this._timeout = null, this._hasMouseInteraction = !1, this._hasKeyboardInteraction = !1, this._setListeners() } static get Default() { return ro } static get DefaultType() { return oo } static get NAME() { return "toast" } show() { N.trigger(this._element, to).defaultPrevented || (this._clearTimeout(), this._config.animation && this._element.classList.add("fade"), this._element.classList.remove(io), d(this._element), this._element.classList.add(no, so), this._queueCallback((() => { this._element.classList.remove(so), N.trigger(this._element, eo), this._maybeScheduleHide() }), this._element, this._config.animation)) } hide() { this.isShown() && (N.trigger(this._element, Js).defaultPrevented || (this._element.classList.add(so), this._queueCallback((() => { this._element.classList.add(io), this._element.classList.remove(so, no), N.trigger(this._element, Zs) }), this._element, this._config.animation))) } dispose() { this._clearTimeout(), this.isShown() && this._element.classList.remove(no), super.dispose() } isShown() { return this._element.classList.contains(no) } _maybeScheduleHide() { this._config.autohide && (this._hasMouseInteraction || this._hasKeyboardInteraction || (this._timeout = setTimeout((() => { this.hide() }), this._config.delay))) } _onInteraction(t, e) { switch (t.type) { case "mouseover": case "mouseout": this._hasMouseInteraction = e; break; case "focusin": case "focusout": this._hasKeyboardInteraction = e }if (e) return void this._clearTimeout(); const i = t.relatedTarget; this._element === i || this._element.contains(i) || this._maybeScheduleHide() } _setListeners() { N.on(this._element, Xs, (t => this._onInteraction(t, !0))), N.on(this._element, Ys, (t => this._onInteraction(t, !1))), N.on(this._element, Us, (t => this._onInteraction(t, !0))), N.on(this._element, Gs, (t => this._onInteraction(t, !1))) } _clearTimeout() { clearTimeout(this._timeout), this._timeout = null } static jQueryInterface(t) { return this.each((function () { const e = ao.getOrCreateInstance(this, t); if ("string" == typeof t) { if (void 0 === e[t]) throw new TypeError(`No method named "${t}"`); e[t](this) } })) } } return R(ao), m(ao), { Alert: Q, Button: Y, Carousel: xt, Collapse: Bt, Dropdown: qi, Modal: On, Offcanvas: qn, Popover: us, ScrollSpy: Es, Tab: Ks, Toast: ao, Tooltip: cs } })); +//# sourceMappingURL=bootstrap.bundle.min.js.map From 85aeacc4ae13c6bb5661455db5d7516f51f26462 Mon Sep 17 00:00:00 2001 From: Justin Adkins Date: Wed, 11 Sep 2024 23:22:35 -0400 Subject: [PATCH 07/24] Rename models and passing tests --- app/controllers/bans_controller.rb | 15 ---- app/controllers/clients_controller.rb | 59 ------------- app/controllers/senders_controller.rb | 44 ++++++++++ app/helpers/clients_helper.rb | 2 - app/helpers/senders_helper.rb | 2 + app/models/{recipient.rb => destination.rb} | 2 +- app/models/{environment.rb => profile.rb} | 10 +-- app/models/{client.rb => sender.rb} | 6 +- app/views/clients/edit.html.erb | 12 --- app/views/clients/index.html.erb | 16 ---- app/views/clients/new.html.erb | 11 --- app/views/clients/show.html.erb | 10 --- app/views/layouts/application.html.erb | 2 +- app/views/{clients => senders}/_form.html.erb | 8 +- .../_sender.html.erb} | 10 +-- app/views/senders/edit.html.erb | 12 +++ app/views/senders/index.html.erb | 16 ++++ app/views/senders/new.html.erb | 11 +++ app/views/senders/show.html.erb | 10 +++ config/routes.rb | 2 +- ...ts.rb => 20240115065325_create_senders.rb} | 11 +-- db/migrate/20240115065341_create_messages.rb | 20 +---- db/migrate/20240912030545_create_bans.rb | 9 ++ db/schema.rb | 86 +++++++++---------- test/controllers/bans_controller_test.rb | 2 +- test/controllers/clients_controller_test.rb | 48 ----------- test/controllers/senders_controller_test.rb | 48 +++++++++++ .../{callbacks.yml => destinations.yml} | 0 .../{environments.yml => profiles.yml} | 0 test/fixtures/recipients.yml | 0 test/fixtures/{clients.yml => senders.yml} | 1 + test/models/ban_test.rb | 14 ++- test/models/client_test.rb | 9 -- test/models/sender_test.rb | 9 ++ test/system/clients_test.rb | 47 ---------- test/system/senders_test.rb | 47 ++++++++++ test/test_helper.rb | 2 +- 37 files changed, 292 insertions(+), 321 deletions(-) delete mode 100644 app/controllers/clients_controller.rb create mode 100644 app/controllers/senders_controller.rb delete mode 100644 app/helpers/clients_helper.rb create mode 100644 app/helpers/senders_helper.rb rename app/models/{recipient.rb => destination.rb} (54%) rename app/models/{environment.rb => profile.rb} (67%) rename app/models/{client.rb => sender.rb} (72%) delete mode 100644 app/views/clients/edit.html.erb delete mode 100644 app/views/clients/index.html.erb delete mode 100644 app/views/clients/new.html.erb delete mode 100644 app/views/clients/show.html.erb rename app/views/{clients => senders}/_form.html.erb (73%) rename app/views/{clients/_client.html.erb => senders/_sender.html.erb} (57%) create mode 100644 app/views/senders/edit.html.erb create mode 100644 app/views/senders/index.html.erb create mode 100644 app/views/senders/new.html.erb create mode 100644 app/views/senders/show.html.erb rename db/migrate/{20240115065325_create_clients.rb => 20240115065325_create_senders.rb} (63%) create mode 100644 db/migrate/20240912030545_create_bans.rb delete mode 100644 test/controllers/clients_controller_test.rb create mode 100644 test/controllers/senders_controller_test.rb rename test/fixtures/{callbacks.yml => destinations.yml} (100%) rename test/fixtures/{environments.yml => profiles.yml} (100%) delete mode 100644 test/fixtures/recipients.yml rename test/fixtures/{clients.yml => senders.yml} (71%) delete mode 100644 test/models/client_test.rb create mode 100644 test/models/sender_test.rb delete mode 100644 test/system/clients_test.rb create mode 100644 test/system/senders_test.rb diff --git a/app/controllers/bans_controller.rb b/app/controllers/bans_controller.rb index 7e3ac64..53b68be 100644 --- a/app/controllers/bans_controller.rb +++ b/app/controllers/bans_controller.rb @@ -1,25 +1,14 @@ class BansController < ApplicationController before_action :set_ban, only: %i[show edit update destroy] - # GET /bans def index @bans = Ban.all end - # GET /bans/1 - def show - end - - # GET /bans/new def new @ban = Ban.new end - # GET /bans/1/edit - def edit - end - - # POST /bans def create @ban = Ban.new(ban_params) @@ -30,7 +19,6 @@ def create end end - # PATCH/PUT /bans/1 def update if @ban.update(ban_params) redirect_to @ban, notice: "Ban was successfully updated.", status: :see_other @@ -39,7 +27,6 @@ def update end end - # DELETE /bans/1 def destroy @ban.destroy! redirect_to bans_url, notice: "Ban was successfully destroyed.", status: :see_other @@ -47,12 +34,10 @@ def destroy private - # Use callbacks to share common setup or constraints between actions. def set_ban @ban = Ban.find(params[:id]) end - # Only allow a list of trusted parameters through. def ban_params params.require(:ban).permit(:address, :reason) end diff --git a/app/controllers/clients_controller.rb b/app/controllers/clients_controller.rb deleted file mode 100644 index d2a0368..0000000 --- a/app/controllers/clients_controller.rb +++ /dev/null @@ -1,59 +0,0 @@ -class ClientsController < ApplicationController - before_action :set_client, only: %i[show edit update destroy] - - # GET /clients - def index - @clients = Client.all - end - - # GET /clients/1 - def show - end - - # GET /clients/new - def new - @client = Client.new - end - - # GET /clients/1/edit - def edit - end - - # POST /clients - def create - @client = Client.new(client_params) - - if @client.save - redirect_to @client, notice: "Client was successfully created." - else - render :new, status: :unprocessable_entity - end - end - - # PATCH/PUT /clients/1 - def update - if @client.update(client_params) - redirect_to @client, notice: "Client was successfully updated.", status: :see_other - else - render :edit, status: :unprocessable_entity - end - end - - # DELETE /clients/1 - def destroy - @client.destroy! - redirect_to clients_url, notice: "Client was successfully destroyed.", status: :see_other - end - - private - - # Use callbacks to share common setup or constraints between actions. - def set_client - @client = Client.find(params[:id]) - end - - # Only allow a list of trusted parameters through. - def client_params - params.require(:client).permit(:name, :state, :key, :secret) - end -end diff --git a/app/controllers/senders_controller.rb b/app/controllers/senders_controller.rb new file mode 100644 index 0000000..f104e78 --- /dev/null +++ b/app/controllers/senders_controller.rb @@ -0,0 +1,44 @@ +class SendersController < ApplicationController + before_action :set_sender, only: %i[show edit update destroy] + + def index + @senders = Sender.all + end + + def new + @sender = Sender.new + end + + def create + @sender = Sender.new(sender_params) + + if @sender.save + redirect_to @sender, notice: "Sender was successfully created." + else + render :new, status: :unprocessable_entity + end + end + + def update + if @sender.update(sender_params) + redirect_to @sender, notice: "Sender was successfully updated.", status: :see_other + else + render :edit, status: :unprocessable_entity + end + end + + def destroy + @sender.destroy! + redirect_to senders_url, notice: "Sender was successfully destroyed.", status: :see_other + end + + private + + def set_sender + @sender = Sender.find(params[:id]) + end + + def sender_params + params.require(:sender).permit(:name, :state, :key, :secret, :address) + end +end diff --git a/app/helpers/clients_helper.rb b/app/helpers/clients_helper.rb deleted file mode 100644 index 9015906..0000000 --- a/app/helpers/clients_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module ClientsHelper -end diff --git a/app/helpers/senders_helper.rb b/app/helpers/senders_helper.rb new file mode 100644 index 0000000..3a64dfb --- /dev/null +++ b/app/helpers/senders_helper.rb @@ -0,0 +1,2 @@ +module SendersHelper +end diff --git a/app/models/recipient.rb b/app/models/destination.rb similarity index 54% rename from app/models/recipient.rb rename to app/models/destination.rb index 87a96cb..9365353 100644 --- a/app/models/recipient.rb +++ b/app/models/destination.rb @@ -1,3 +1,3 @@ -class Recipient < ApplicationRecord +class Destination < ApplicationRecord encrypts :address, deterministic: true end diff --git a/app/models/environment.rb b/app/models/profile.rb similarity index 67% rename from app/models/environment.rb rename to app/models/profile.rb index a96626a..050164c 100644 --- a/app/models/environment.rb +++ b/app/models/profile.rb @@ -1,13 +1,13 @@ -class Environment < ApplicationRecord - belongs_to :client +class Profile < ApplicationRecord + belongs_to :sender - validates :name, presence: true, uniqueness: {scope: %i[client]} + validates :name, presence: true, uniqueness: {scope: %i[sender]} # approved: Messages are delivered without any filtering # hold: Messages are saved but not delivered # ignored: Messages are not saved but no error is returned # rejected: Messages are not saved and an error is returned - # rerouted: Messages are sent to the Client owner - # whitelisted: Messages are only delivered to recipeints whitelisted for the Client + # rerouted: Messages are sent to the Sender owner + # whitelisted: Messages are only delivered to recipeints whitelisted for the Sender enum :state, %w[approved hold ignored rejected rerouted whitelisted].index_by(&:itself), default: :hold end diff --git a/app/models/client.rb b/app/models/sender.rb similarity index 72% rename from app/models/client.rb rename to app/models/sender.rb index cf34f56..fa28ee2 100644 --- a/app/models/client.rb +++ b/app/models/sender.rb @@ -1,7 +1,7 @@ -class Client < ApplicationRecord - has_many :environments +class Sender < ApplicationRecord + has_many :profiles has_many :messages - has_many :recipients, through: :messages + has_many :destinations, through: :messages validates :name, presence: true, uniqueness: true validates :state, presence: true diff --git a/app/views/clients/edit.html.erb b/app/views/clients/edit.html.erb deleted file mode 100644 index 7110143..0000000 --- a/app/views/clients/edit.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -<% content_for :title, "Editing client" %> - -

Editing client

- -<%= render "form", client: @client %> - -
- -
- <%= link_to "Show this client", @client %> | - <%= link_to "Back to clients", clients_path %> -
diff --git a/app/views/clients/index.html.erb b/app/views/clients/index.html.erb deleted file mode 100644 index 870fc74..0000000 --- a/app/views/clients/index.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -

<%= notice %>

- -<% content_for :title, "Clients" %> - -

Clients

- -
- <% @clients.each do |client| %> - <%= render client %> -

- <%= link_to "Show this client", client %> -

- <% end %> -
- -<%= link_to "New client", new_client_path %> diff --git a/app/views/clients/new.html.erb b/app/views/clients/new.html.erb deleted file mode 100644 index 9f460cb..0000000 --- a/app/views/clients/new.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<% content_for :title, "New client" %> - -

New client

- -<%= render "form", client: @client %> - -
- -
- <%= link_to "Back to clients", clients_path %> -
diff --git a/app/views/clients/show.html.erb b/app/views/clients/show.html.erb deleted file mode 100644 index 20794cf..0000000 --- a/app/views/clients/show.html.erb +++ /dev/null @@ -1,10 +0,0 @@ -

<%= notice %>

- -<%= render @client %> - -
- <%= link_to "Edit this client", edit_client_path(@client) %> | - <%= link_to "Back to clients", clients_path %> - - <%= button_to "Destroy this client", @client, method: :delete %> -
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index c007097..7dd502c 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -30,7 +30,7 @@ Bans