Full Code of loco-rs/loco for AI

master e9598a6822c5 cached
794 files
2.4 MB
680.2k tokens
2070 symbols
1 requests
Download .txt
Showing preview only (2,703K chars total). Download the full file or copy to clipboard to get everything.
Repository: loco-rs/loco
Branch: master
Commit: e9598a6822c5
Files: 794
Total size: 2.4 MB

Directory structure:
gitextract_8x970ict/

├── .cargo/
│   └── config.toml
├── .clippy.toml
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   ├── config.yml
│   │   ├── feature-request.md
│   │   └── suggestion.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── docs.yml
│       ├── loco-gen-ci.yml
│       ├── loco-gen-deploy.yml
│       ├── loco-new.yml
│       ├── loco-rs-ci-sanity.yml
│       └── loco-rs-ci.yml
├── .gitignore
├── .rustfmt.toml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.toml
├── DEVELOPMENT.md
├── LICENSE
├── README-pt_BR.md
├── README-zh_CN.md
├── README.es.md
├── README.fr.md
├── README.ja.md
├── README.ko.md
├── README.md
├── README.ru.md
├── SECURITY.md
├── build/
│   └── embedded_assets.rs
├── build.rs
├── docs-site/
│   ├── .gitignore
│   ├── config.toml
│   ├── content/
│   │   ├── _index.md
│   │   ├── authors/
│   │   │   ├── _index.md
│   │   │   ├── limpidcrypto.md
│   │   │   └── team-loco.md
│   │   ├── blog/
│   │   │   ├── _index.md
│   │   │   ├── angular-frontend.md
│   │   │   ├── axum-session.md
│   │   │   ├── deploy-aws.md
│   │   │   ├── frontend-website.md
│   │   │   └── hello-world.md
│   │   ├── casts/
│   │   │   ├── 001-dynamic-responses-and-content-types.md
│   │   │   ├── 002-routes-and-prefixes.md
│   │   │   ├── 003-scaffolding-crud-with-html.md
│   │   │   ├── 004-creating-tasks.md
│   │   │   ├── 005-testing-tasks.md
│   │   │   ├── 006-mailers.md
│   │   │   ├── 007-htmx.md
│   │   │   └── _index.md
│   │   ├── docs/
│   │   │   ├── _index.md
│   │   │   ├── extras/
│   │   │   │   ├── _index.md
│   │   │   │   ├── authentication.md
│   │   │   │   ├── pluggability.md
│   │   │   │   ├── upgrades.md
│   │   │   │   └── websocket.md
│   │   │   ├── getting-started/
│   │   │   │   ├── _index.md
│   │   │   │   ├── axum-users.md
│   │   │   │   ├── guide.md
│   │   │   │   ├── starters.md
│   │   │   │   └── tour/
│   │   │   │       └── index.md
│   │   │   ├── infrastructure/
│   │   │   │   ├── _index.md
│   │   │   │   ├── cache.md
│   │   │   │   ├── data.md
│   │   │   │   ├── deployment.md
│   │   │   │   └── storage.md
│   │   │   ├── processing/
│   │   │   │   ├── _index.md
│   │   │   │   ├── mailers.md
│   │   │   │   ├── scheduler.md
│   │   │   │   ├── task.md
│   │   │   │   └── workers.md
│   │   │   ├── resources/
│   │   │   │   ├── _index.md
│   │   │   │   ├── around-the-web.md
│   │   │   │   └── faq.md
│   │   │   └── the-app/
│   │   │       ├── _index.md
│   │   │       ├── controller.md
│   │   │       ├── models.md
│   │   │       ├── views.md
│   │   │       └── your-project.md
│   │   └── privacy-policy/
│   │       └── _index.md
│   ├── package.json
│   ├── static/
│   │   ├── ahrefs_f06cfb9c2671c1b7a5b6eec0d47a07719bd6d5a2240b829cad6a3f40684fa370
│   │   ├── js/
│   │   │   ├── main.js
│   │   │   └── search.js
│   │   ├── styles/
│   │   │   └── styles.css
│   │   ├── syntax-theme-dark.css
│   │   └── syntax-theme-light.css
│   ├── styles/
│   │   └── styles.css
│   ├── tailwind.config.js
│   ├── templates/
│   │   ├── 404.html
│   │   ├── base.html
│   │   ├── blog/
│   │   │   ├── atom.xml
│   │   │   ├── page.html
│   │   │   ├── rss.xml
│   │   │   └── section.html
│   │   ├── casts/
│   │   │   ├── page.html
│   │   │   └── section.html
│   │   ├── docs/
│   │   │   ├── page.html
│   │   │   └── section.html
│   │   ├── index.html
│   │   ├── macros/
│   │   │   ├── docs-edit-page.html
│   │   │   ├── docs-navigation.html
│   │   │   ├── docs-sidebar.html
│   │   │   ├── docs-toc.html
│   │   │   ├── footer.html
│   │   │   ├── header.html
│   │   │   ├── javascript.html
│   │   │   ├── page-publish-metadata.html
│   │   │   └── youtube.html
│   │   ├── page.html
│   │   ├── section.html
│   │   ├── shortcodes/
│   │   │   └── get_env.html
│   │   ├── taxonomy_list.html
│   │   └── taxonomy_single.html
│   └── translations/
│       └── tour-fr.md
├── loco-cli/
│   ├── .gitignore
│   ├── .rustfmt.toml
│   ├── Cargo.toml
│   ├── README.md
│   └── src/
│       ├── bin/
│       │   └── main.rs
│       └── lib.rs
├── loco-gen/
│   ├── .gitattributes
│   ├── Cargo.toml
│   ├── src/
│   │   ├── controller.rs
│   │   ├── infer.rs
│   │   ├── lib.rs
│   │   ├── mappings.json
│   │   ├── migration.rs
│   │   ├── model.rs
│   │   ├── scaffold.rs
│   │   ├── snapshots/
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_big_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_bool].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_double].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_float].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_string].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_big_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_bool].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_double].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_float].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_string].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_big_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_bool].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_double].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_float].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_string].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_int!_big_int!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_int^_big_int^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_int_big_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_unsigned!_big_unsigned!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_unsigned^_big_unsigned^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_unsigned_big_unsigned].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_binary_len!_binary_len!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_binary_len^_binary_len^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_binary_len_binary_len].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_blob!_blob!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_blob^_blob^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_blob_blob].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_bool!_bool!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_bool_bool].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date!_date!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date^_date^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date_date].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date_time!_date_time!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date_time^_date_time^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date_time_date_time].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal!_decimal!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal^_decimal^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_decimal].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_len!_decimal_len!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_len^_decimal_len^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_len_decimal_len].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_double!_double!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_double^_double^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_double_double].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_float!_float!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_float^_float^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_float_float].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_int!_int!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_int^_int^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_int_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_json!_json!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_json_json].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_jsonb!_jsonb!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_jsonb^_jsonb^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_jsonb_jsonb].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_money!_money!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_money^_money^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_money_money].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_int!_small_int!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_int^_small_int^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_int_small_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_unsigned!_small_unsigned!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_unsigned^_small_unsigned^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_unsigned_small_unsigned].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_string!_string!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_string^_string^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_string_string].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_text!_text!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_text^_text^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_text_text].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_tstz!_tstz!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_tstz_tstz].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_unsigned!_unsigned!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_unsigned^_unsigned^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_unsigned_unsigned].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_uuid!_uuid!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_uuid^_uuid^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_uuid_uuid].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_var_binary!_var_binary!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_var_binary^_var_binary^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_var_binary_var_binary].snap
│   │   │   └── loco_gen__tera_ext__tests__can_render_view_field.snap
│   │   ├── template.rs
│   │   ├── templates/
│   │   │   ├── controller/
│   │   │   │   ├── api/
│   │   │   │   │   ├── controller.t
│   │   │   │   │   └── test.t
│   │   │   │   ├── html/
│   │   │   │   │   ├── controller.t
│   │   │   │   │   └── view.t
│   │   │   │   └── htmx/
│   │   │   │       ├── controller.t
│   │   │   │       └── view.t
│   │   │   ├── data/
│   │   │   │   ├── 0_mod.t
│   │   │   │   ├── data.t
│   │   │   │   ├── mod.t
│   │   │   │   └── struct.t
│   │   │   ├── deployment/
│   │   │   │   ├── docker/
│   │   │   │   │   ├── docker.t
│   │   │   │   │   └── ignore.t
│   │   │   │   └── nginx/
│   │   │   │       └── nginx.t
│   │   │   ├── mailer/
│   │   │   │   ├── html.t
│   │   │   │   ├── mailer.t
│   │   │   │   ├── subject.t
│   │   │   │   └── text.t
│   │   │   ├── migration/
│   │   │   │   ├── add_columns.t
│   │   │   │   ├── add_references.t
│   │   │   │   ├── empty.t
│   │   │   │   ├── join_table.t
│   │   │   │   └── remove_columns.t
│   │   │   ├── model/
│   │   │   │   ├── model.t
│   │   │   │   └── test.t
│   │   │   ├── scaffold/
│   │   │   │   ├── api/
│   │   │   │   │   ├── controller.t
│   │   │   │   │   └── test.t
│   │   │   │   ├── html/
│   │   │   │   │   ├── base.t
│   │   │   │   │   ├── controller.t
│   │   │   │   │   ├── view.t
│   │   │   │   │   ├── view_create.t
│   │   │   │   │   ├── view_edit.t
│   │   │   │   │   ├── view_list.t
│   │   │   │   │   └── view_show.t
│   │   │   │   └── htmx/
│   │   │   │       ├── base.t
│   │   │   │       ├── controller.t
│   │   │   │       ├── view.t
│   │   │   │       ├── view_create.t
│   │   │   │       ├── view_edit.t
│   │   │   │       ├── view_list.t
│   │   │   │       └── view_show.t
│   │   │   ├── scheduler/
│   │   │   │   └── scheduler.t
│   │   │   ├── task/
│   │   │   │   ├── task.t
│   │   │   │   └── test.t
│   │   │   └── worker/
│   │   │       ├── test.t
│   │   │       └── worker.t
│   │   ├── tera_ext.rs
│   │   └── testutil.rs
│   └── tests/
│       ├── db.rs
│       ├── mod.rs
│       ├── snapshots/
│       │   ├── db__migrations_flow_postgres.snap
│       │   ├── db__migrations_flow_sqlite.snap
│       │   ├── r#mod__db__migrations_flow_postgres.snap
│       │   └── r#mod__db__migrations_flow_sqlite.snap
│       └── templates/
│           ├── controller.rs
│           ├── deployment.rs
│           ├── mailer.rs
│           ├── migration.rs
│           ├── mod.rs
│           ├── model.rs
│           ├── scaffold.rs
│           ├── scheduler.rs
│           ├── snapshots/
│           │   ├── generate[controller_file]@Api_controller.snap
│           │   ├── generate[controller_file]@Api_scaffold.snap
│           │   ├── generate[controller_file]@Html_controller.snap
│           │   ├── generate[controller_file]@Html_scaffold.snap
│           │   ├── generate[controller_file]@Htmx_controller.snap
│           │   ├── generate[controller_file]@Htmx_scaffold.snap
│           │   ├── generate[controller_file]@scheduler.snap
│           │   ├── generate[controller_file]@task.snap
│           │   ├── generate[controller_file]@worker.snap
│           │   ├── generate[docker_file_[0]_[false]]@deployment.snap
│           │   ├── generate[docker_file_[0]_[true]]@deployment.snap
│           │   ├── generate[docker_file_[2]_[false]]@deployment.snap
│           │   ├── generate[docker_file_[2]_[true]]@deployment.snap
│           │   ├── generate[html_t_file]@mailer.snap
│           │   ├── generate[mailer_mod_rs]@mailer.snap
│           │   ├── generate[migration_file]@Api_scaffold.snap
│           │   ├── generate[migration_file]@Html_scaffold.snap
│           │   ├── generate[migration_file]@Htmx_scaffold.snap
│           │   ├── generate[migration_file]@add_column_migration.snap
│           │   ├── generate[migration_file]@add_reference_migration.snap
│           │   ├── generate[migration_file]@create_join_table_migration.snap
│           │   ├── generate[migration_file]@create_join_table_without_tz_migration.snap
│           │   ├── generate[migration_file]@create_table_migration.snap
│           │   ├── generate[migration_file]@create_table_without_tz_migration.snap
│           │   ├── generate[migration_file]@empty_migration.snap
│           │   ├── generate[migration_file]@model.snap
│           │   ├── generate[migration_file]@remove_columns_migration.snap
│           │   ├── generate[nginx]@deployment.snap
│           │   ├── generate[subject_t_file]@mailer.snap
│           │   ├── generate[test_model]@Api_scaffold.snap
│           │   ├── generate[test_model]@Html_scaffold.snap
│           │   ├── generate[test_model]@Htmx_scaffold.snap
│           │   ├── generate[test_model]@model.snap
│           │   ├── generate[tests_controller_mod_rs]@Api_controller.snap
│           │   ├── generate[tests_task_file]@task.snap
│           │   ├── generate[tests_worker_file]@worker.snap
│           │   ├── generate[text_t_file]@mailer.snap
│           │   ├── generate[views_[create]]@Html_scaffold.snap
│           │   ├── generate[views_[create]]@Htmx_scaffold.snap
│           │   ├── generate[views_[edit]]@Html_scaffold.snap
│           │   ├── generate[views_[edit]]@Htmx_scaffold.snap
│           │   ├── generate[views_[list]]@Html_scaffold.snap
│           │   ├── generate[views_[list]]@Htmx_scaffold.snap
│           │   ├── generate[views_[show]]@Html_scaffold.snap
│           │   ├── generate[views_[show]]@Htmx_scaffold.snap
│           │   ├── generate[views_rs]@Html_scaffold.snap
│           │   ├── generate[views_rs]@Htmx_scaffold.snap
│           │   ├── generate_result@add_column_migration.snap
│           │   ├── generate_result@add_reference_migration.snap
│           │   ├── generate_result@create_join_table_migration.snap
│           │   ├── generate_result@create_join_table_without_tz_migration.snap
│           │   ├── generate_result@create_table_migration.snap
│           │   ├── generate_result@create_table_without_tz_migration.snap
│           │   ├── generate_result@empty_migration.snap
│           │   ├── generate_result@remove_columns_migration.snap
│           │   ├── generate_results@Api_controller.snap
│           │   ├── generate_results@Api_scaffold.snap
│           │   ├── generate_results@Html_controller.snap
│           │   ├── generate_results@Html_scaffold.snap
│           │   ├── generate_results@Htmx_controller.snap
│           │   ├── generate_results@Htmx_scaffold.snap
│           │   ├── inject[.config_toml]@deployment.snap
│           │   ├── inject[app_rs]@Api_controller.snap
│           │   ├── inject[app_rs]@Api_scaffold.snap
│           │   ├── inject[app_rs]@Html_controller.snap
│           │   ├── inject[app_rs]@Html_scaffold.snap
│           │   ├── inject[app_rs]@Htmx_controller.snap
│           │   ├── inject[app_rs]@Htmx_scaffold.snap
│           │   ├── inject[app_rs]@task.snap
│           │   ├── inject[app_rs]@worker.snap
│           │   ├── inject[controller_mod_rs]@Api_controller.snap
│           │   ├── inject[controller_mod_rs]@Api_scaffold.snap
│           │   ├── inject[controller_mod_rs]@Html_controller.snap
│           │   ├── inject[controller_mod_rs]@Html_scaffold.snap
│           │   ├── inject[controller_mod_rs]@Htmx_controller.snap
│           │   ├── inject[controller_mod_rs]@Htmx_scaffold.snap
│           │   ├── inject[mailer_mod_rs]@mailer.snap
│           │   ├── inject[migration_lib]@Api_scaffold.snap
│           │   ├── inject[migration_lib]@Html_scaffold.snap
│           │   ├── inject[migration_lib]@Htmx_scaffold.snap
│           │   ├── inject[migration_lib]@add_column_migration.snap
│           │   ├── inject[migration_lib]@add_reference_migration.snap
│           │   ├── inject[migration_lib]@create_join_table_migration.snap
│           │   ├── inject[migration_lib]@create_join_table_without_tz_migration.snap
│           │   ├── inject[migration_lib]@create_table_migration.snap
│           │   ├── inject[migration_lib]@create_table_without_tz_migration.snap
│           │   ├── inject[migration_lib]@empty_migration.snap
│           │   ├── inject[migration_lib]@model.snap
│           │   ├── inject[migration_lib]@remove_columns_migration.snap
│           │   ├── inject[task_mod_rs]@task.snap
│           │   ├── inject[test_mod]@Api_scaffold.snap
│           │   ├── inject[test_mod]@Html_scaffold.snap
│           │   ├── inject[test_mod]@Htmx_scaffold.snap
│           │   ├── inject[test_mod]@model.snap
│           │   ├── inject[tests_controller_mod_rs]@Api_controller.snap
│           │   ├── inject[tests_task_mod]@task.snap
│           │   ├── inject[tests_worker_mod]@worker.snap
│           │   ├── inject[views_[GET]]@Html_controller.snap
│           │   ├── inject[views_[GET]]@Htmx_controller.snap
│           │   ├── inject[views_[POST]]@Html_controller.snap
│           │   ├── inject[views_[POST]]@Htmx_controller.snap
│           │   ├── inject[views_mod_rs]@Html_scaffold.snap
│           │   ├── inject[views_mod_rs]@Htmx_scaffold.snap
│           │   └── inject[worker_mod_rs]@worker.snap
│           ├── task.rs
│           ├── utils.rs
│           └── worker.rs
├── loco-new/
│   ├── .gitignore
│   ├── Cargo.lock
│   ├── Cargo.toml
│   ├── README.md
│   ├── base_template/
│   │   ├── .cargo/
│   │   │   └── config.toml.t
│   │   ├── .github/
│   │   │   └── workflows/
│   │   │       └── ci.yaml.t
│   │   ├── .gitignore
│   │   ├── .rustfmt.toml
│   │   ├── Cargo.toml.t
│   │   ├── README.md
│   │   ├── assets/
│   │   │   ├── i18n/
│   │   │   │   ├── de-DE/
│   │   │   │   │   └── main.ftl
│   │   │   │   ├── en-US/
│   │   │   │   │   └── main.ftl
│   │   │   │   └── shared.ftl
│   │   │   ├── static/
│   │   │   │   └── 404.html
│   │   │   └── views/
│   │   │       └── home/
│   │   │           └── hello.html
│   │   ├── config/
│   │   │   ├── development.yaml.t
│   │   │   └── test.yaml.t
│   │   ├── examples/
│   │   │   └── playground.rs.t
│   │   ├── frontend/
│   │   │   ├── .gitignore
│   │   │   ├── README.md
│   │   │   ├── biome.json
│   │   │   ├── package.json
│   │   │   ├── rsbuild.config.ts
│   │   │   ├── src/
│   │   │   │   ├── LocoSplash.tsx
│   │   │   │   ├── env.d.ts
│   │   │   │   ├── index.css
│   │   │   │   └── index.tsx
│   │   │   └── tsconfig.json
│   │   ├── migration/
│   │   │   ├── Cargo.toml.t
│   │   │   └── src/
│   │   │       ├── lib.rs.t
│   │   │       └── m20220101_000001_users.rs
│   │   ├── src/
│   │   │   ├── app.rs.t
│   │   │   ├── bin/
│   │   │   │   ├── main.rs.t
│   │   │   │   └── tool.rs.t
│   │   │   ├── controllers/
│   │   │   │   ├── auth.rs
│   │   │   │   ├── home.rs
│   │   │   │   └── mod.rs.t
│   │   │   ├── data/
│   │   │   │   └── mod.rs.t
│   │   │   ├── fixtures/
│   │   │   │   └── users.yaml
│   │   │   ├── initializers/
│   │   │   │   ├── mod.rs.t
│   │   │   │   └── view_engine.rs
│   │   │   ├── lib.rs.t
│   │   │   ├── mailers/
│   │   │   │   ├── auth/
│   │   │   │   │   ├── forgot/
│   │   │   │   │   │   ├── html.t
│   │   │   │   │   │   ├── subject.t
│   │   │   │   │   │   └── text.t
│   │   │   │   │   ├── magic_link/
│   │   │   │   │   │   ├── html.t
│   │   │   │   │   │   ├── subject.t
│   │   │   │   │   │   └── text.t
│   │   │   │   │   └── welcome/
│   │   │   │   │       ├── html.t
│   │   │   │   │       ├── subject.t
│   │   │   │   │       └── text.t
│   │   │   │   ├── auth.rs
│   │   │   │   └── mod.rs
│   │   │   ├── models/
│   │   │   │   ├── _entities/
│   │   │   │   │   ├── mod.rs.t
│   │   │   │   │   ├── prelude.rs.t
│   │   │   │   │   └── users.rs
│   │   │   │   ├── mod.rs.t
│   │   │   │   └── users.rs
│   │   │   ├── tasks/
│   │   │   │   ├── mod.rs.t
│   │   │   │   └── user_create.rs
│   │   │   ├── views/
│   │   │   │   ├── auth.rs
│   │   │   │   ├── home.rs
│   │   │   │   └── mod.rs.t
│   │   │   └── workers/
│   │   │       ├── downloader.rs
│   │   │       └── mod.rs.t
│   │   └── tests/
│   │       ├── mod.rs.t
│   │       ├── models/
│   │       │   ├── mod.rs.t
│   │       │   ├── snapshots/
│   │       │   │   ├── can_create_with_password@users.snap
│   │       │   │   ├── can_find_by_email@users-2.snap
│   │       │   │   ├── can_find_by_email@users.snap
│   │       │   │   ├── can_find_by_pid@users-2.snap
│   │       │   │   ├── can_find_by_pid@users.snap
│   │       │   │   ├── can_validate_model@users.snap
│   │       │   │   └── handle_create_with_password_with_duplicate@users.snap
│   │       │   └── users.rs.t
│   │       ├── requests/
│   │       │   ├── auth.rs.t
│   │       │   ├── home.rs.t
│   │       │   ├── mod.rs.t
│   │       │   ├── prepare_data.rs.t
│   │       │   └── snapshots/
│   │       │       ├── can_auth_with_magic_link@auth_request.snap
│   │       │       ├── can_get_current_user@auth_request.snap
│   │       │       ├── can_login_without_verify@auth_request.snap
│   │       │       ├── can_register@auth_request.snap
│   │       │       ├── can_reset_password@auth_request.snap
│   │       │       ├── login_with_invalid_password@auth_request.snap
│   │       │       ├── login_with_valid_password@auth_request.snap
│   │       │       └── resend_verification_user@auth_request.snap
│   │       ├── tasks/
│   │       │   ├── mod.rs.t
│   │       │   └── user_create.rs.t
│   │       └── workers/
│   │           └── mod.rs
│   ├── devnew.sh
│   ├── setup.rhai
│   ├── src/
│   │   ├── bin/
│   │   │   └── main.rs
│   │   ├── generator/
│   │   │   ├── executer/
│   │   │   │   ├── filesystem.rs
│   │   │   │   ├── inmem.rs
│   │   │   │   └── mod.rs
│   │   │   ├── mod.rs
│   │   │   └── template.rs
│   │   ├── lib.rs
│   │   ├── settings.rs
│   │   └── wizard.rs
│   └── tests/
│       ├── assertion/
│       │   ├── mod.rs
│       │   ├── string.rs
│       │   ├── toml.rs
│       │   └── yaml.rs
│       ├── mod.rs
│       ├── templates/
│       │   ├── asset.rs
│       │   ├── auth.rs
│       │   ├── background.rs
│       │   ├── db.rs
│       │   ├── features.rs
│       │   ├── initializers.rs
│       │   ├── mailer.rs
│       │   ├── mod.rs
│       │   ├── module_name.rs
│       │   └── snapshots/
│       │       ├── r#mod__templates__asset__cargo_dependencies_Clientside.snap
│       │       ├── r#mod__templates__asset__cargo_dependencies_None.snap
│       │       ├── r#mod__templates__asset__cargo_dependencies_Serverside.snap
│       │       ├── r#mod__templates__auth__src_app_rs_auth_false_None.snap
│       │       ├── r#mod__templates__auth__src_app_rs_auth_false_Sqlite.snap
│       │       ├── r#mod__templates__auth__src_app_rs_auth_true_None.snap
│       │       ├── r#mod__templates__auth__src_app_rs_auth_true_Sqlite.snap
│       │       ├── r#mod__templates__background__src_app_rs_Async.snap
│       │       ├── r#mod__templates__background__src_app_rs_Blocking.snap
│       │       ├── r#mod__templates__background__src_app_rs_None.snap
│       │       ├── r#mod__templates__background__src_app_rs_Queue.snap
│       │       ├── r#mod__templates__db__cargo_dependencies_None.snap
│       │       ├── r#mod__templates__db__cargo_dependencies_Postgres.snap
│       │       ├── r#mod__templates__db__cargo_dependencies_Sqlite.snap
│       │       ├── r#mod__templates__db__config_development_yaml_config_database_Postgres.snap
│       │       ├── r#mod__templates__db__config_development_yaml_config_database_Sqlite.snap
│       │       ├── r#mod__templates__db__config_test_yaml_config_database_Postgres.snap
│       │       ├── r#mod__templates__db__config_test_yaml_config_database_Sqlite.snap
│       │       ├── r#mod__templates__db__src_app_rs_None.snap
│       │       ├── r#mod__templates__db__src_app_rs_Postgres.snap
│       │       ├── r#mod__templates__db__src_app_rs_Sqlite.snap
│       │       ├── r#mod__templates__initializers__src_app_rs_with_initializers.snap
│       │       ├── r#mod__templates__initializers__src_app_rs_without_initializers.snap
│       │       ├── r#mod__templates__mailer__cargo_dependencies_mailer_false.snap
│       │       └── r#mod__templates__mailer__cargo_dependencies_mailer_true.snap
│       └── wizard/
│           ├── mod.rs
│           └── new.rs
├── snipdoc.yml
├── src/
│   ├── app.rs
│   ├── auth/
│   │   ├── jwt.rs
│   │   ├── mod.rs
│   │   └── snapshots/
│   │       ├── loco_rs__auth__jwt__tests__token expired.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom array claims.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom boolean claims.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom nested array claims.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom nested claims.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom number claims.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom string claims.snap
│   │       └── loco_rs__auth__jwt__tests__valid token.snap
│   ├── banner.rs
│   ├── bgworker/
│   │   ├── mod.rs
│   │   ├── pg.rs
│   │   ├── redis.rs
│   │   ├── snapshots/
│   │   │   ├── loco_rs__bgworker__pg__tests__can_complete_job_with_interval.snap
│   │   │   ├── loco_rs__bgworker__pg__tests__can_dequeue.snap
│   │   │   ├── loco_rs__bgworker__pg__tests__can_enqueue.snap
│   │   │   ├── loco_rs__bgworker__pg__tests__can_fail_job.snap
│   │   │   ├── loco_rs__bgworker__pg__tests__can_initialize_database.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__can_complete_job_with_interval.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__can_dequeue.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__can_enqueue.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__can_fail_job.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__sqlt_loco_queue.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__sqlt_loco_queue_lock.snap
│   │   │   └── loco_rs__bgworker__tests__can_dump_jobs.snap
│   │   └── sqlt.rs
│   ├── boot.rs
│   ├── cache/
│   │   ├── drivers/
│   │   │   ├── inmem.rs
│   │   │   ├── mod.rs
│   │   │   ├── null.rs
│   │   │   └── redis.rs
│   │   └── mod.rs
│   ├── cargo_config.rs
│   ├── cli.rs
│   ├── config.rs
│   ├── controller/
│   │   ├── app_routes.rs
│   │   ├── backtrace.rs
│   │   ├── describe.rs
│   │   ├── extractor/
│   │   │   ├── auth.rs
│   │   │   ├── mod.rs
│   │   │   ├── shared_store.rs
│   │   │   ├── snapshots/
│   │   │   │   ├── loco_rs__controller__extractor__auth__tests__extract_from_bearer.snap
│   │   │   │   ├── loco_rs__controller__extractor__auth__tests__extract_from_cookie.snap
│   │   │   │   ├── loco_rs__controller__extractor__auth__tests__extract_from_default.snap
│   │   │   │   ├── loco_rs__controller__extractor__auth__tests__extract_from_multiple_locations.snap
│   │   │   │   └── loco_rs__controller__extractor__auth__tests__extract_from_query.snap
│   │   │   └── validate.rs
│   │   ├── format.rs
│   │   ├── middleware/
│   │   │   ├── _archive/
│   │   │   │   └── content_etag.rs
│   │   │   ├── catch_panic.rs
│   │   │   ├── compression.rs
│   │   │   ├── cors.rs
│   │   │   ├── etag.rs
│   │   │   ├── fallback.html
│   │   │   ├── fallback.rs
│   │   │   ├── format.rs
│   │   │   ├── limit_payload.rs
│   │   │   ├── logger.rs
│   │   │   ├── mod.rs
│   │   │   ├── powered_by.rs
│   │   │   ├── remote_ip.rs
│   │   │   ├── request_id.rs
│   │   │   ├── secure_headers.json
│   │   │   ├── secure_headers.rs
│   │   │   ├── snapshots/
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_OPTIONS_[allow_origins].snap
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_[default].snap
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_[with_allow_headers].snap
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_[with_allow_methods].snap
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_[with_expose_headers].snap
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_[with_max_age].snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-2.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-3.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-4.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-5.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-6.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-7.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-8.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing.snap
│   │   │   │   ├── loco_rs__controller__middleware__request_id__tests__create_or_fetch_request_id-2.snap
│   │   │   │   ├── loco_rs__controller__middleware__request_id__tests__create_or_fetch_request_id-3.snap
│   │   │   │   ├── loco_rs__controller__middleware__request_id__tests__create_or_fetch_request_id-4.snap
│   │   │   │   ├── loco_rs__controller__middleware__request_id__tests__create_or_fetch_request_id-5.snap
│   │   │   │   ├── loco_rs__controller__middleware__request_id__tests__create_or_fetch_request_id.snap
│   │   │   │   ├── loco_rs__controller__middleware__secure_headers__tests__can_override_headers.snap
│   │   │   │   ├── loco_rs__controller__middleware__secure_headers__tests__can_set_headers.snap
│   │   │   │   └── loco_rs__controller__middleware__secure_headers__tests__default_is_github_preset.snap
│   │   │   ├── static_assets.rs
│   │   │   ├── static_assets_embedded.rs
│   │   │   └── timeout.rs
│   │   ├── mod.rs
│   │   ├── monitoring.rs
│   │   ├── routes.rs
│   │   ├── snapshots/
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]_health].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]_ping].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]_readiness].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]api[slash]loco-rs].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]api[slash]loco].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]api[slash]v1[slash]notes].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]api[slash]v1[slash]users].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]multiple1].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]multiple2].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]multiple3].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]normalizer[slash]loco[slash]rs].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]normalizer[slash]multiple-end].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]normalizer[slash]multiple-start].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]normalizer[slash]no-slash].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]normalizer].snap
│   │   │   ├── loco_rs__controller__format__tests__builder_cookies_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_empty_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_html_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_json_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_redirect_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_redirect_with_custom_header_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_template_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_text_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_view_response-2.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_view_response.snap
│   │   │   ├── loco_rs__controller__format__tests__empty_json_response_format.snap
│   │   │   ├── loco_rs__controller__format__tests__empty_response_format.snap
│   │   │   ├── loco_rs__controller__format__tests__html_response_format.snap
│   │   │   ├── loco_rs__controller__format__tests__json_response_format.snap
│   │   │   ├── loco_rs__controller__format__tests__redirect_response.snap
│   │   │   ├── loco_rs__controller__format__tests__template_response.snap
│   │   │   ├── loco_rs__controller__format__tests__text_response_format.snap
│   │   │   ├── loco_rs__controller__format__tests__view_response-2.snap
│   │   │   ├── loco_rs__controller__format__tests__view_response.snap
│   │   │   └── loco_rs__controller__format__tests__yaml_response_format.snap
│   │   └── views/
│   │       ├── engine.rs
│   │       ├── engine_embedded.rs
│   │       ├── mod.rs
│   │       ├── pagination.rs
│   │       └── tera_builtins/
│   │           ├── filters/
│   │           │   ├── mod.rs
│   │           │   └── number.rs
│   │           └── mod.rs
│   ├── data.rs
│   ├── db.rs
│   ├── depcheck.rs
│   ├── doctor.rs
│   ├── env_vars.rs
│   ├── environment.rs
│   ├── errors.rs
│   ├── hash.rs
│   ├── initializers/
│   │   ├── extra_db.rs
│   │   ├── mod.rs
│   │   └── multi_db.rs
│   ├── lib.rs
│   ├── logger.rs
│   ├── mailer/
│   │   ├── email_sender.rs
│   │   ├── mod.rs
│   │   ├── snapshots/
│   │   │   ├── loco_rs__mailer__email_sender__tests__can_send_email.snap
│   │   │   ├── loco_rs__mailer__email_sender__tests__can_send_email_with_custom_headers.snap
│   │   │   └── loco_rs__mailer__template__tests__can_render_template.snap
│   │   └── template.rs
│   ├── model/
│   │   ├── mod.rs
│   │   └── query/
│   │       ├── dsl/
│   │       │   ├── date_range.rs
│   │       │   └── mod.rs
│   │       ├── mod.rs
│   │       └── paginate/
│   │           └── mod.rs
│   ├── prelude.rs
│   ├── scheduler.rs
│   ├── schema.rs
│   ├── snapshots/
│   │   ├── loco_rs__auth__tests__token expired.snap
│   │   ├── loco_rs__auth__tests__valid token.snap
│   │   ├── loco_rs__db__tests__dump_tables_sqlite_all_types.snap
│   │   ├── loco_rs__db__tests__dump_tables_sqlite_all_types_roundtrip.snap
│   │   ├── loco_rs__scheduler__tests__can_display_scheduler.snap
│   │   ├── loco_rs__scheduler__tests__can_prepare_command_[shell].snap
│   │   ├── loco_rs__scheduler__tests__can_prepare_command_[task].snap
│   │   ├── loco_rs__validation__tests__struct-[foo-bar].snap
│   │   ├── loco_rs__validation__tests__struct-[foo].snap
│   │   ├── loco_rs__worker__tests__default_custom_queues-2.snap
│   │   ├── loco_rs__worker__tests__default_custom_queues-3.snap
│   │   └── loco_rs__worker__tests__default_custom_queues.snap
│   ├── storage/
│   │   ├── contents.rs
│   │   ├── drivers/
│   │   │   ├── aws.rs
│   │   │   ├── azure.rs
│   │   │   ├── gcp.rs
│   │   │   ├── local.rs
│   │   │   ├── mem.rs
│   │   │   ├── mod.rs
│   │   │   ├── null.rs
│   │   │   └── opendal_adapter.rs
│   │   ├── mod.rs
│   │   ├── strategies/
│   │   │   ├── backup.rs
│   │   │   ├── mirror.rs
│   │   │   ├── mod.rs
│   │   │   └── single.rs
│   │   └── stream.rs
│   ├── task.rs
│   ├── tera.rs
│   ├── testing/
│   │   ├── db.rs
│   │   ├── mod.rs
│   │   ├── prelude.rs
│   │   ├── redaction.rs
│   │   ├── request.rs
│   │   └── selector.rs
│   ├── tests_cfg/
│   │   ├── app.rs
│   │   ├── config.rs
│   │   ├── controllers/
│   │   │   ├── auth.rs
│   │   │   ├── home.rs
│   │   │   └── mod.rs
│   │   ├── db.rs
│   │   ├── mod.rs
│   │   ├── postgres.rs
│   │   ├── queue.rs
│   │   ├── redis.rs
│   │   └── task.rs
│   └── validation.rs
├── tests/
│   ├── build_scripts/
│   │   ├── embedded_assets.rs
│   │   ├── mod.rs
│   │   └── snapshots/
│   │       ├── r#mod__build_scripts__embedded_assets__build_static_assets_static.snap
│   │       ├── r#mod__build_scripts__embedded_assets__build_static_assets_templates.snap
│   │       ├── r#mod__build_scripts__embedded_assets__collected_all_files.snap
│   │       ├── r#mod__build_scripts__embedded_assets__collected_css_files.snap
│   │       ├── r#mod__build_scripts__embedded_assets__complex_template_inheritance.snap
│   │       ├── r#mod__build_scripts__embedded_assets__discovered_directories.snap
│   │       ├── r#mod__build_scripts__embedded_assets__empty_static_assets_rs.snap
│   │       ├── r#mod__build_scripts__embedded_assets__empty_templates_rs.snap
│   │       ├── r#mod__build_scripts__embedded_assets__static_assets_rs.snap
│   │       ├── r#mod__build_scripts__embedded_assets__template_inheritance.snap
│   │       └── r#mod__build_scripts__embedded_assets__view_templates_rs.snap
│   ├── controller/
│   │   ├── extractor/
│   │   │   ├── auth/
│   │   │   │   ├── api_token.rs
│   │   │   │   ├── jwt.rs
│   │   │   │   ├── jwt_with_user.rs
│   │   │   │   └── mod.rs
│   │   │   ├── mod.rs
│   │   │   ├── shared_store.rs
│   │   │   └── validate.rs
│   │   ├── from_ref.rs
│   │   ├── into_response.rs
│   │   ├── middlewares.rs
│   │   ├── mod.rs
│   │   └── snapshots/
│   │       ├── cors_[default]@middlewares.snap
│   │       ├── cors_[disabled]@middlewares.snap
│   │       ├── cors_[with_allow_headers]@middlewares.snap
│   │       ├── cors_[with_allow_methods]@middlewares.snap
│   │       ├── cors_[with_max_age]@middlewares.snap
│   │       ├── panic@middlewares.snap
│   │       ├── secure_headers_[empty]_overrides[none]@middlewares.snap
│   │       ├── secure_headers_[github]_overrides[Content-Security-Policy]@middlewares.snap
│   │       └── secure_headers_[none]_overrides[none]@middlewares.snap
│   ├── fixtures/
│   │   ├── email_template/
│   │   │   └── test/
│   │   │       ├── html.t
│   │   │       ├── subject.t
│   │   │       └── text.t
│   │   └── queue/
│   │       └── jobs.yaml
│   ├── infra_cfg/
│   │   ├── mod.rs
│   │   └── server.rs
│   └── mod.rs
└── xtask/
    ├── .rustfmt.toml
    ├── Cargo.toml
    ├── README.md
    └── src/
        ├── bin/
        │   └── main.rs
        ├── bump_version.rs
        ├── ci.rs
        ├── errors.rs
        ├── lib.rs
        ├── out.rs
        ├── prompt.rs
        ├── utils.rs
        └── versions.rs

================================================
FILE CONTENTS
================================================

================================================
FILE: .cargo/config.toml
================================================
[alias]

xtask = "run --package xtask --"

# https://github.com/rust-lang/rust/issues/141626
# (can be removed once link.exe is fixed)
[target.x86_64-pc-windows-msvc]
linker = "rust-lld"


================================================
FILE: .clippy.toml
================================================
cognitive-complexity-threshold = 40


================================================
FILE: .gitattributes
================================================
* linguist-vendored
*.rs linguist-vendored=false


================================================
FILE: .github/FUNDING.yml
================================================
github: loco-rs 

================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: Bug Report
about: Report behavior that deviates from specification or expectation
title: ""
labels: assessment
assignees: ""
---

**Description**

Provide a clear and concise explanation of the bug, including references to any conflicting documentation or an elucidation of why the current functionality doesn't align with your expectations.

**To Reproduce**

Please outline the steps to replicate the bug, and if possible, provide a comprehensive code example consisting of both `main.rs` and `Cargo.toml`` files. A complete and functional code snippet would be highly appreciated.

**Expected Behavior**

A clear and concise description of what you expected to happen.

**Environment:**

**Additional Context**

Include additional context about the issue in this section. For instance, share insights into the bug's discovery process or any hypotInclude additional context about the issue in this section. For instance, share insights into the bug's discovery process or any hypotheses you may have regarding the root cause or specific aspects where Loco may be malfunctioning.


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true
contact_links:
  - name: Question
    url: https://github.com/loco-rs/loco/discussions
    about: Please ask questions or raise indefinite concerns on Discussions


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.md
================================================
---
name: Feature Request
about: Suggest a new feature
title: ""
labels: enhancement
assignees: ""
---

## Feature Request

**Is your feature request related to a problem? Please describe.**

Provide a succinct and clear description of the problem. For example, I encounter an issue when...

**Describe the solution you'd like**

Articulate a clear and concise depiction of your desired outcome.

**Describe alternatives you've considered**

Offer a clear and concise description of any alternative solutions or features you have contemplated.


================================================
FILE: .github/ISSUE_TEMPLATE/suggestion.md
================================================
---
name: Suggestion
about: Suggest a change or improvement to existing functionality

title: ""
labels: assessment
assignees: ""
---

**Description**

Please provide a well-defined and succinct explanation of the issue. Include references to any conflicting documentation or clarify why the current functionality deviates from your expectations.

**To Reproduce**

Please outline the steps to replicate the bug, and if possible, provide a comprehensive code example consisting of both `main.rs` and `Cargo.toml`` files. A complete and functional code snippet would be highly appreciated.

**Expected Behavior**

Provide a straightforward and brief explanation of your anticipated outcome.

**Environment:**

**Additional Context**

Include additional details about the issue in this section. For instance, share insights into how you discovered the bug or any hypotheses you may have regarding what might be causing the problem with Loco.


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "cargo"
    directory: "/"
    schedule:
      interval: "daily"
    open-pull-requests-limit: 0
    
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "daily"


================================================
FILE: .github/workflows/docs.yml
================================================
name: "[docs]"

on:
  push:
    branches:
      - master
  pull_request:

env:
  RUST_TOOLCHAIN: stable
  TOOLCHAIN_PROFILE: minimal

jobs:
  check:
    runs-on: ubuntu-latest

    permissions:
      contents: read

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
      - run: cargo install snipdoc --features exec
      - run: snipdoc check
        continue-on-error: true
        env:
          SNIPDOC_SKIP_EXEC_COMMANDS: true


================================================
FILE: .github/workflows/loco-gen-ci.yml
================================================
name: "[loco-gen:ci]"

on:
  push:
    branches:
      - master
    paths:
      - "loco-gen/**"
  pull_request:
    paths:
      - "loco-gen/**"

env:
  RUST_TOOLCHAIN: stable
  TOOLCHAIN_PROFILE: minimal

defaults:
  run:
    working-directory: ./loco-gen

jobs:
  style:
    runs-on: ubuntu-latest

    permissions:
      contents: read

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          components: rustfmt
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
      - name: Run cargo fmt
        run: cargo fmt --all -- --check
      - name: Run cargo clippy
        run: cargo clippy --all-features -- -D warnings -W clippy::pedantic -W clippy::nursery -W rust-2018-idioms

  test:
    needs: [style]
    runs-on: ubuntu-latest

    permissions:
      contents: read

    services:
      postgres:
        image: postgres
        env:
          POSTGRES_DB: postgres_test
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
        ports:
          - "5432:5432"
        # Set health checks to wait until postgres has started
        options: --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2

      - name: Install seaorm cli
        run: cargo install sea-orm-cli

      - run: |
          cargo install --path ../loco-new

      - name: Run cargo test
        run: cargo test --all-features
        env:
          LOCO_DEV_MODE_PATH: ${{ github.workspace }}
          DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres_test


================================================
FILE: .github/workflows/loco-gen-deploy.yml
================================================
name: "[loco-gen-deploy]"
on:
  schedule:
    - cron: "0 0 * * *"

env:
  RUST_TOOLCHAIN: stable
  TOOLCHAIN_PROFILE: minimal

jobs:
  g-deploy-docker:
    # This workflow creates a new Loco application and builds a Docker image
    # We only want this to run on the main repository (loco-rs/loco) and not on forks because:
    # 1. It consumes GitHub Actions minutes unnecessarily on forks
    # 2. The Docker build and deployment is specific to the main repository
    # 3. Forks typically don't need to run this automated deployment process
    if: github.repository == 'loco-rs/loco'
    runs-on: ubuntu-latest

    permissions:
      contents: read

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2

      - name: Install seaorm cli
        run: cargo install sea-orm-cli

      - name: install 'loco new'
        run: |
          cargo install loco

      - name: create myapp
        run: |
          loco new -n myapp --db sqlite --bg async --assets serverside -a

      - name:
        run: cargo loco generate deployment docker && docker build -t demo .
        working-directory: ./myapp



================================================
FILE: .github/workflows/loco-new.yml
================================================
name: "[loco-new:ci]"

on:
  push:
    branches:
      - master
    paths:
      - "loco-new/**"
      - "loco-gen/**"
  pull_request:
    paths:
      - "loco-new/**"
      - "loco-gen/**"

env:
  RUST_TOOLCHAIN: stable
  TOOLCHAIN_PROFILE: minimal

jobs:
  style:
    runs-on: ubuntu-latest

    permissions:
      contents: read

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          components: rustfmt
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
      - run: cargo fmt --all -- --check
        working-directory: ./loco-new
      - name: Run cargo clippy
        run: cargo clippy --all-features -- -D warnings -W clippy::pedantic -W clippy::nursery -W rust-2018-idioms
        working-directory: ./loco-new

  test:
    # needs: [style]
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]

    permissions:
      contents: read

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6

      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}

      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2

      - name: Configure sccache
        run: |
          echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV
          echo "SCCACHE_GHA_ENABLED=true" >> $GITHUB_ENV

      - name: Run sccache-cache
        uses: mozilla-actions/sccache-action@v0.0.9

      - name: Install seaorm cli
        run: cargo install sea-orm-cli

      - name: Free Disk Space
        if: ${{ matrix.os == 'ubuntu-latest' }}
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false

      - name: Run cargo test
        run: cargo test --all-features -- --test-threads 1
        working-directory: ./loco-new
        env:
          LOCO_DEV_MODE_PATH: ${{ github.workspace }}
          # NOTE NOTE NOTE: this is for optimizing build and may result in strange behavior
          CARGO_TARGET_DIR: /tmp/shared-target


================================================
FILE: .github/workflows/loco-rs-ci-sanity.yml
================================================
# To optimize CI runtime:
# A simpler "sanity check" workflow is introduced. 
# This workflow only runs if changes in the PR do NOT include 
# the `loco-gen` or `loco-new` paths.
# (When changes are made to `loco-gen` or `loco-new`, 
# we run comprehensive tests to validate every generator command 
# and template option.)

# Purpose of the sanity check:
# It performs basic validation by comparing the local changes 
# against the templates. 
# If any breaking changes are detected in the templates, 
# the sanity check will fail, signaling an issue.

name: "[loco_rs:sanity]"

on:
  push:
    branches:
      - master
  pull_request:

env:
  RUST_TOOLCHAIN: stable
  TOOLCHAIN_PROFILE: minimal

jobs:
  sanity:
    runs-on: ubuntu-latest

    permissions:
      contents: read

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2

      - name: Install seaorm cli
        run: cargo install sea-orm-cli
        
      - run: cargo install --path loco-new
      
      - run: |
          loco new -n myappdb --db sqlite --bg async --assets serverside -a
          cd myappdb
          cargo check
          cargo build --release
        env:
          LOCO_DEV_MODE_PATH: ${{ github.workspace }}
          
      - run: |
          loco new -n myapp --db none --bg async --assets none -a
          cd myapp
          cargo check
          cargo build --release
        env:
          LOCO_DEV_MODE_PATH: ${{ github.workspace }}

      

================================================
FILE: .github/workflows/loco-rs-ci.yml
================================================
name: "[loco_rs:ci]"

on:
  push:
    branches:
      - master
  pull_request:

env:
  RUST_TOOLCHAIN: stable
  TOOLCHAIN_PROFILE: minimal

jobs:
  style:
    runs-on: ubuntu-latest

    permissions:
      contents: read

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
          components: rustfmt
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
      - name: Run cargo fmt
        run: cargo fmt --all -- --check
      - name: Run cargo clippy
        run: cargo clippy --all-features -- -D warnings -W clippy::pedantic -W clippy::nursery -W rust-2018-idioms

  check:
    needs: [style]
    runs-on: ubuntu-latest

    permissions:
      contents: read

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
      - uses: taiki-e/install-action@v2
        with:
          tool: cargo-hack
      - run: cargo hack check --each-feature

  build:
    needs: [check, style]
    runs-on: ubuntu-latest

    permissions:
      contents: read

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2

      - name: Run cargo build
        run: cargo build --release
  test:
    needs: [check, style]
    runs-on: ubuntu-latest

    permissions:
      contents: read

    steps:
      - name: Checkout the code
        uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: ${{ env.RUST_TOOLCHAIN }}
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2

      - name: Run cargo test
        run: cargo test --all-features --workspace --exclude loco-gen --exclude loco


================================================
FILE: .gitignore
================================================
# local dev
todo.txt
todo.md
examples/demo2
examples/myapp
*.sqlite
*.sqlite-wal
*.sqlite-shm

*.sqlite3
*.sqlite3-wal
*.sqlite3-shm

# IDE config files
.idea
.vscode

**/config/local.yaml
**/config/*.local.yaml

# Local Netlify folder
.netlify


### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Rust ###
# Generated by Cargo
# will have compiled files and executables
target/
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

## Frontend
# Various node lock files; so people don't accidentally commit them while
# updating the template
starters/saas/frontend/package-lock.json
starters/saas/frontend/yarn.lock
starters/saas/frontend/pnpm-lock.yaml


example

================================================
FILE: .rustfmt.toml
================================================
max_width = 100
use_small_heuristics = "Default"


================================================
FILE: CHANGELOG.md
================================================
# Changelog



##  Unreleased
- Fix `cargo fmt` error in `loco-new` ([#1669](https://github.com/loco-rs/loco/pull/1669))
- Fix UUID pattern in form field generation ([#1665](https://github.com/loco-rs/loco/pull/1665))
- Add tests for auth extractor ([#1671](https://github.com/loco-rs/loco/pull/1671))
- Fix Clippy warnings for Rust 1.92 ([#1705](https://github.com/loco-rs/loco/pull/1705))
- Add email headers support to mailer ([#1700](https://github.com/loco-rs/loco/pull/1700))
- Wrap `TeraView` in `Arc` to reduce runtime memory usage ([#1703](https://github.com/loco-rs/loco/pull/1703))
- Allow overriding a secure header ([#1659](https://github.com/loco-rs/loco/pull/1659))
- Add “create user” task ([#1670](https://github.com/loco-rs/loco/pull/1670))
- Add `UuidUniqWithDefault` and `UuidWithDefault` types ([#1642](https://github.com/loco-rs/loco/pull/1642))
- Refactor users model to reuse `find_by_api_key` in `Authenticable` ([#1706](https://github.com/loco-rs/loco/pull/1706))
- Split error detail generic parameters ([#1709](https://github.com/loco-rs/loco/pull/1709))
- Update `loco-new` for new Rhai version ([#1704](https://github.com/loco-rs/loco/pull/1704))

### Breaking Changes
In file `src/initializers/view_engine.rs`, modify the code lines in `after_routes`:

Before

```rust
async fn after_routes(&self, router: AxumRouter, _ctx: &AppContext) -> Result<AxumRouter> {
                :
    engines::TeraView::build()?.post_process(move |tera| {
                :
```

After (use `build_with_post_process` instead of `post_process`)

```rust
async fn after_routes(&self, router: AxumRouter, _ctx: &AppContext) -> Result<AxumRouter> {
                :
    engines::TeraView::build_with_post_process(move |tera| {
                :
}
```



## v0.16.4 
- Feat: decouple JWT authentication from database dependency. [https://github.com/loco-rs/loco/pull/1546](https://github.com/loco-rs/loco/pull/1546)
- Fix: add sqlx dependency to with-db feature. [https://github.com/loco-rs/loco/pull/1557](https://github.com/loco-rs/loco/pull/1557)
- Remove the deprecated `--link` generate command and fix the table name creation. [https://github.com/loco-rs/loco/pull/1556](https://github.com/loco-rs/loco/pull/1556)
- Support underscore for migration join table. [https://github.com/loco-rs/loco/pull/1562](https://github.com/loco-rs/loco/pull/1562)
- Fix: resolve deployment CLI argument parsing issue. [https://github.com/loco-rs/loco/pull/1566](https://github.com/loco-rs/loco/pull/1566)
- Add database enum support (Postgres only). [https://github.com/loco-rs/loco/pull/1593](https://github.com/loco-rs/loco/pull/1568)
- Remove duplicated #[async_trait::async_trait]. [https://github.com/loco-rs/loco/pull/1593](https://github.com/loco-rs/loco/pull/1572)
- Clippy fixes for Rust 1.89. [https://github.com/loco-rs/loco/pull/1593](https://github.com/loco-rs/loco/pull/1593)
- Improvement: do not hot-reload unless files have changed. [https://github.com/loco-rs/loco/pull/1552](https://github.com/loco-rs/loco/pull/1552)
- Feat: add --without-tz flag for controlling timestamp generation. [https://github.com/loco-rs/loco/pull/1592](https://github.com/loco-rs/loco/pull/1592)
- Support extra fields when generating the join table migration. [https://github.com/loco-rs/loco/pull/1595](https://github.com/loco-rs/loco/pull/1595)
- Convert validator to trait-based API (add ValidatorTrait, keep derive adapter, update docs). [https://github.com/loco-rs/loco/pull/1597](https://github.com/loco-rs/loco/pull/1597)
- Rename dockerfile to Dockerfile. [https://github.com/loco-rs/loco/pull/1574](https://github.com/loco-rs/loco/pull/1574)
- Enable edit CORS expose headers. [https://github.com/loco-rs/loco/pull/1599](https://github.com/loco-rs/loco/pull/1599)
- Adding new imports about multipart. [https://github.com/loco-rs/loco/pull/1600](https://github.com/loco-rs/loco/pull/1600)
- Adding readiness default endpoint. [https://github.com/loco-rs/loco/pull/1563](https://github.com/loco-rs/loco/pull/1563)
- Add Route methods to make collecting and nesting easier. [https://github.com/loco-rs/loco/pull/1608](https://github.com/loco-rs/loco/pull/1608)
- Add streaming support for both download and upload. [https://github.com/loco-rs/loco/pull/1610](https://github.com/loco-rs/loco/pull/1610)
- Fix Clippy for Rust 1.90. [https://github.com/loco-rs/loco/pull/1630](https://github.com/loco-rs/loco/pull/1630)
- Loco CLI: Update rhai version. [https://github.com/loco-rs/loco/pull/1631](https://github.com/loco-rs/loco/pull/1631)


## v0.16.3
- Support nullable foreign keys with `references?` syntax. [https://github.com/loco-rs/loco/pull/1544](https://github.com/loco-rs/loco/pull/1544)
- **HOTFIX**: **Breaking changes** Fixed a critical issue introduced in version `v0.16.2` that caused `cargo build --release` to fail after merging #1540. [https://github.com/loco-rs/loco/pull/1551](https://github.com/loco-rs/loco/pull/1551)
- Add an API to re-send verification mail. [https://github.com/loco-rs/loco/pull/1456](https://github.com/loco-rs/loco/pull/1456)
- Adding to ci cargo build --release. [https://github.com/loco-rs/loco/pull/1553](https://github.com/loco-rs/loco/pull/1553)

### Breaking Changes

In file `src/initializers/view_engine.rs`, modify the method `after_routes`:

Before

```rust
async fn after_routes(&self, router: AxumRouter, _ctx: &AppContext) -> Result<AxumRouter> {
	#[allow(unused_mut)]
	let mut tera_engine = engines::TeraView::build()?;
	if std::path::Path::new(I18N_DIR).exists() {
		let arc = ArcLoader::builder(&I18N_DIR, unic_langid::langid!("en-US"))
			.shared_resources(Some(&[I18N_SHARED.into()]))
			.customize(|bundle| bundle.set_use_isolating(false))
			.build()
			.map_err(|e| Error::string(&e.to_string()))?;
		#[cfg(debug_assertions)]
		tera_engine
			.tera
			.lock()
			.expect("lock")
			.register_function("t", FluentLoader::new(arc));

		#[cfg(not(debug_assertions))]
		tera_engine
			.tera
			.register_function("t", FluentLoader::new(arc));
		info!("locales loaded");
	}

	Ok(router.layer(Extension(ViewEngine::from(tera_engine))))
}
```

After (use `post_process` to add i18n initialization code)

```rust
async fn after_routes(&self, router: AxumRouter, _ctx: &AppContext) -> Result<AxumRouter> {
	let tera_engine = if std::path::Path::new(I18N_DIR).exists() {
		let arc = std::sync::Arc::new(
			ArcLoader::builder(&I18N_DIR, unic_langid::langid!("en-US"))
				.shared_resources(Some(&[I18N_SHARED.into()]))
				.customize(|bundle| bundle.set_use_isolating(false))
				.build()
				.map_err(|e| Error::string(&e.to_string()))?,
		);
		info!("locales loaded");

		engines::TeraView::build()?.post_process(move |tera| {
			tera.register_function("t", FluentLoader::new(arc.clone()));
			Ok(())
		})?
	} else {
		engines::TeraView::build()?
	};

	Ok(router.layer(Extension(ViewEngine::from(tera_engine))))
}
```
## v0.16.2
- Update auth import in the Authentication document. [https://github.com/loco-rs/loco/pull/1531](https://github.com/loco-rs/loco/pull/1531)
- Adding cache control header to the static asset middleware. [https://github.com/loco-rs/loco/pull/1535](https://github.com/loco-rs/loco/pull/1535)
- Fix borrow checker when sending config to handle_job_command when feature with-db is off. [https://github.com/loco-rs/loco/pull/1536](https://github.com/loco-rs/loco/pull/1536)
- feat: add initializer health checks to doctor command. [https://github.com/loco-rs/loco/pull/1537](https://github.com/loco-rs/loco/pull/1537)
- Update shuttle template to 0.56. [https://github.com/loco-rs/loco/pull/1518](https://github.com/loco-rs/loco/pull/1518)
- Encapsulate post-processing into Tera engine creation. [https://github.com/loco-rs/loco/pull/1540](https://github.com/loco-rs/loco/pull/1540)
- Adding QueryValidateWithMessage. [https://github.com/loco-rs/loco/pull/1521](https://github.com/loco-rs/loco/pull/1521)
- Add S3 driver with credentials and endpoint support. [https://github.com/loco-rs/loco/pull/1539](https://github.com/loco-rs/loco/pull/1539)

## v0.16.1
- fix clippy result_large_err. [https://github.com/loco-rs/loco/pull/1496](https://github.com/loco-rs/loco/pull/1496)
- chore: remove async-std. [https://github.com/loco-rs/loco/pull/1492](https://github.com/loco-rs/loco/pull/1492)
- fix: Bump shuttle version to 0.55.0. [https://github.com/loco-rs/loco/pull/1488](https://github.com/loco-rs/loco/pull/1488)
- Change the Docker building image to 1.87. [https://github.com/loco-rs/loco/pull/1475](https://github.com/loco-rs/loco/pull/1475)
- Fix Clippy warnings for Rust 1.88 stable. [https://github.com/loco-rs/loco/pull/1519](https://github.com/loco-rs/loco/pull/1519) 
- Remove Migrator from boot_test_* doc comments. [https://github.com/loco-rs/loco/pull/1512](https://github.com/loco-rs/loco/pull/1512) 
- fix: use rust-lld linker on Windows. [https://github.com/loco-rs/loco/pull/1508](https://github.com/loco-rs/loco/pull/1508) 
- Fix precompressed in static assets. [https://github.com/loco-rs/loco/pull/1524](https://github.com/loco-rs/loco/pull/1524) 
- Support multiple JWT locations. [https://github.com/loco-rs/loco/pull/1497](https://github.com/loco-rs/loco/pull/1497) 

## v0.16.0

**Note:** For detailed upgrade steps for breaking changes, see the [upgrade guide](https://loco.rs/docs/extras/upgrades/#upgrade-from-0-15-x-to-0-16-x).

- chore: improve readability and performance by using map_err in Model. [https://github.com/loco-rs/loco/pull/1311](https://github.com/loco-rs/loco/pull/1311)
- Allow testing the controller by passing a cookie. [https://github.com/loco-rs/loco/pull/1326](https://github.com/loco-rs/loco/pull/1326)
- Support BigInt in the scaffold Array. [https://github.com/loco-rs/loco/pull/1304](https://github.com/loco-rs/loco/pull/1304)
- Add `escape` Tera function to the scaffold list template. [https://github.com/loco-rs/loco/pull/1337](https://github.com/loco-rs/loco/pull/1337)
- Return a specific error when logging in with a non-existent email. [https://github.com/loco-rs/loco/pull/1336](https://github.com/loco-rs/loco/pull/1336)
- Return a specific error when trying to verify with an invalid token. [https://github.com/loco-rs/loco/pull/1340](https://github.com/loco-rs/loco/pull/1340)
- Clippy 1.86. [https://github.com/loco-rs/loco/pull/1353](https://github.com/loco-rs/loco/pull/1353)
- Fix the DB creation. [https://github.com/loco-rs/loco/pull/1352](https://github.com/loco-rs/loco/pull/1352)
- YAML responses. [https://github.com/loco-rs/loco/pull/1360](https://github.com/loco-rs/loco/pull/1360)
- Swap to the validators' built-in email validation. [https://github.com/loco-rs/loco/pull/1359](https://github.com/loco-rs/loco/pull/1359)
- Cancellation tokens for the Postgres and SQLite background workers. [https://github.com/loco-rs/loco/pull/1365](https://github.com/loco-rs/loco/pull/1365)
- docs: testing auth routes. [https://github.com/loco-rs/loco/pull/1303](https://github.com/loco-rs/loco/pull/1303)
- Add comprehensive tests for the task module. [https://github.com/loco-rs/loco/pull/1386](https://github.com/loco-rs/loco/pull/1386)
- Add comprehensive test coverage for the data module. [https://github.com/loco-rs/loco/pull/1387](https://github.com/loco-rs/loco/pull/1387)
- Add validator extractors test suite. [https://github.com/loco-rs/loco/pull/1388](https://github.com/loco-rs/loco/pull/1388)
- **Breaking changes** Replace sidekiq job management: existing Redis jobs incompatible. [https://github.com/loco-rs/loco/pull/1384](https://github.com/loco-rs/loco/pull/1384)
- **Breaking changes** Add generic type support to the Cache API: cache method calls need type parameters. [https://github.com/loco-rs/loco/pull/1385](https://github.com/loco-rs/loco/pull/1385)
- Adding cache redis driver + configuration instead of enabling from code. [https://github.com/loco-rs/loco/pull/1389](https://github.com/loco-rs/loco/pull/1389)
- Ability to configure pragma for SQLite. [https://github.com/loco-rs/loco/pull/1346](https://github.com/loco-rs/loco/pull/1346)
- **Breaking changes** swap to validators builtin email validation: custom email validator syntax changed. [https://github.com/loco-rs/loco/pull/1359](https://github.com/loco-rs/loco/pull/1359)
- Optimize worker tag filtering string handling. [https://github.com/loco-rs/loco/pull/1396](https://github.com/loco-rs/loco/pull/1396)
- Add test coverage for db.rs. [https://github.com/loco-rs/loco/pull/1400](https://github.com/loco-rs/loco/pull/1400)
- Allow storage of arbitrary custom objects in AppContext. [https://github.com/loco-rs/loco/pull/1404](https://github.com/loco-rs/loco/pull/1404)
- Improve deployment generator CLI. [https://github.com/loco-rs/loco/pull/1413](https://github.com/loco-rs/loco/pull/1413)
- Move auth and validate to the extractor folder. [https://github.com/loco-rs/loco/pull/1414](https://github.com/loco-rs/loco/pull/1414)
- Hot reload on extended Tera templates. [https://github.com/loco-rs/loco/pull/1416](https://github.com/loco-rs/loco/pull/1416)
- **Breaking changes** Update the `init_logger` to use `AppContext` instead of config: function signature changed. [https://github.com/loco-rs/loco/pull/1418](https://github.com/loco-rs/loco/pull/1418)
- Support embedded assets. [https://github.com/loco-rs/loco/pull/1427](https://github.com/loco-rs/loco/pull/1427)
- **Removed dependencies:**
  - [`hyper`](https://github.com/loco-rs/loco/pull/1430)
  - [`thousands`](https://github.com/loco-rs/loco/pull/1431)
  - [`cfg-if`](https://github.com/loco-rs/loco/pull/1432)
  - [`reqwest`](https://github.com/loco-rs/loco/pull/1434)
  - [`serde_variant`](https://github.com/loco-rs/loco/pull/1493)

* **Dependency updates:**
  - Bumped [`tokio`] to `1.45` and [`tokio-util`] to `0.7` ([#1435](https://github.com/loco-rs/loco/pull/1435))
  - Bumped [`colored`] to `3.0` ([#1437](https://github.com/loco-rs/loco/pull/1437))
  - Bumped [`rand`] to `0.9` ([#1439](https://github.com/loco-rs/loco/pull/1439))
  - Bumped [`duct`] to `1.0` ([#1438](https://github.com/loco-rs/loco/pull/1438))
  - Bumped [`redis`] to `0.31`, [`bb8`] to `0.9`, and [`bb8-redis`] to `0.23` ([commit `7e7be`](https://github.com/loco-rs/loco/commit/7e7bebe15f74c377c93d979aab41c52eb871d667))
  - Updated Loco template crates ([#1440](https://github.com/loco-rs/loco/pull/1440))

- Support custom flags from `sea-orm entity`. [https://github.com/loco-rs/loco/pull/1442](https://github.com/loco-rs/loco/pull/1442)
- Better `loco new` cleanup folders. [https://github.com/loco-rs/loco/pull/1429](https://github.com/loco-rs/loco/pull/1429)
- Remove legacy mailer derive macro code. [https://github.com/loco-rs/loco/pull/1472](https://github.com/loco-rs/loco/pull/1472)
- Make extract_token and get_jwt_from_config fn public. [https://github.com/loco-rs/loco/pull/1495](https://github.com/loco-rs/loco/pull/1495)

## v0.15.0

- Added total_items to pagination view & response. [https://github.com/loco-rs/loco/pull/1197](https://github.com/loco-rs/loco/pull/1197)
- Flatten (de)serialization of custom user claims. [https://github.com/loco-rs/loco/pull/1159](https://github.com/loco-rs/loco/pull/1159)
- Updated validator to 0.20. [https://github.com/loco-rs/loco/pull/1199](https://github.com/loco-rs/loco/pull/1199)
- Scaffold v2. [https://github.com/loco-rs/loco/pull/1209](https://github.com/loco-rs/loco/pull/1209)
- Fix generator Docker deployment to support both server-side and client-side rendering. [https://github.com/loco-rs/loco/pull/1227](https://github.com/loco-rs/loco/pull/1227)
- Docs: num_workers worker configuration. [https://github.com/loco-rs/loco/pull/1242](https://github.com/loco-rs/loco/pull/1242)
- Smoother model validations. [https://github.com/loco-rs/loco/pull/1233](https://github.com/loco-rs/loco/pull/1233)
- Docs: num_workers worker configuration. [https://github.com/loco-rs/loco/pull/1242](https://github.com/loco-rs/loco/pull/1242)
- Ignore SQLite WAL and SHM files and update Cargo watch crate docs. [https://github.com/loco-rs/loco/pull/1254](https://github.com/loco-rs/loco/pull/1254)
- Remove fs-err crate. [https://github.com/loco-rs/loco/pull/1253](https://github.com/loco-rs/loco/pull/1253)
- Allows to run scheduler as part of cargo loco start. [https://github.com/loco-rs/loco/pull/1247](https://github.com/loco-rs/loco/pull/1247)
- Added prefix and route nesting to AppRoutes. [https://github.com/loco-rs/loco/pull/1241](https://github.com/loco-rs/loco/pull/1241)
- Replace hyper crate with axum. [https://github.com/loco-rs/loco/pull/1258](https://github.com/loco-rs/loco/pull/1258)
- Remove mime crate. [https://github.com/loco-rs/loco/pull/1256](https://github.com/loco-rs/loco/pull/1256)
- Support async tests. [https://github.com/loco-rs/loco/pull/1237](https://github.com/loco-rs/loco/pull/1237)
- Change job queue status from cli. [https://github.com/loco-rs/loco/pull/1228](https://github.com/loco-rs/loco/pull/1228)
- Handle panics in queue worker. [https://github.com/loco-rs/loco/pull/1274](https://github.com/loco-rs/loco/pull/1274)
- Schema with defaults. [https://github.com/loco-rs/loco/pull/1273](https://github.com/loco-rs/loco/pull/1273)
- Add data subsystem. [https://github.com/loco-rs/loco/pull/1267](https://github.com/loco-rs/loco/pull/1267)
- Add "endpoint" arg to azure storage builder.[https://github.com/loco-rs/loco/pull/1317](https://github.com/loco-rs/loco/pull/1317)
- Improve readability and performance by using map_err in Model. [https://github.com/loco-rs/loco/pull/1311](https://github.com/loco-rs/loco/pull/1311)

### Breaking Changes

In module `loco_rs::auth::jwt` in struct `JWT`, the impl method `generate_token` signature has changed.
Migration:

Before

```rust
jwt.generate_token(&expiration, pid.clone(), None);
```

After

```rust
jwt.generate_token(expiration, pid.clone(), Map::new());
//                 ^ no "&"                 ^ serde_json::map (doesn't allocate in constructor)
```

## v0.14.1

- Fix: bump shuttle to 0.51.0. [https://github.com/loco-rs/loco/pull/1169](https://github.com/loco-rs/loco/pull/1169)
- Return 422 status code for JSON rejection errors. [https://github.com/loco-rs/loco/pull/1173](https://github.com/loco-rs/loco/pull/1173)
- Address clippy warnings for Rust stable 1.84. [https://github.com/loco-rs/loco/pull/1168](https://github.com/loco-rs/loco/pull/1168)
- Bump shuttle to 0.51.0. [https://github.com/loco-rs/loco/pull/1169](https://github.com/loco-rs/loco/pull/1169)
- Return 422 status code for JSON rejection errors. [https://github.com/loco-rs/loco/pull/1173](https://github.com/loco-rs/loco/pull/1173)
- Return json validation details response. [https://github.com/loco-rs/loco/pull/1174](https://github.com/loco-rs/loco/pull/1174)
- Fix example command after generating schedule. [https://github.com/loco-rs/loco/pull/1176](https://github.com/loco-rs/loco/pull/1176)
- Fixed independent features. [https://github.com/loco-rs/loco/pull/1177](https://github.com/loco-rs/loco/pull/1177)
- Custom response header for redirect. [https://github.com/loco-rs/loco/pull/1186](https://github.com/loco-rs/loco/pull/1186)
- Added run_on_start feature to scheduler. [https://github.com/loco-rs/loco/pull/1184](https://github.com/loco-rs/loco/pull/1184)
- feat: public jwt extractor from non-mutable reference to parts. [https://github.com/loco-rs/loco/pull/1190](https://github.com/loco-rs/loco/pull/1190)

## v0.14

- feat: smart migration generator. you can now generate migration based on naming them for creating a table, adding columns, references, join tables and more. [https://github.com/loco-rs/loco/pull/1086](https://github.com/loco-rs/loco/pull/1086)
- feat: `cargo loco routes` will now pretty-print routes
- fix: guard jwt error behind feature flag. [https://github.com/loco-rs/loco/pull/1032](https://github.com/loco-rs/loco/pull/1032)
- fix: logger file_appender not using the seperated format setting. [https://github.com/loco-rs/loco/pull/1036](https://github.com/loco-rs/loco/pull/1036)
- seed cli command. [https://github.com/loco-rs/loco/pull/1046](https://github.com/loco-rs/loco/pull/1046)
- Updated validator to 0.19. [https://github.com/loco-rs/loco/pull/993](https://github.com/loco-rs/loco/pull/993)
  ### Breaking Changes
  Bump validator to 0.19 in your local `Cargo.toml`
- Testing helpers: simplified function calls + adding html selector. [https://github.com/loco-rs/loco/pull/1047](https://github.com/loco-rs/loco/pull/1047)

  ### Breaking Changes

  #### Updated Import Paths

  The testing module import path has been updated. To adapt your code, update imports from:

  ```rust
  use loco_rs::testing;
  ```

  to:

  ```rust
  use testing::prelude::*;
  ```

  #### Simplified Function Calls

  Function calls within the testing module no longer require the testing:: prefix. Update your code accordingly. For example:

  Before:

  ```rust
  let boot = testing::boot_test::<App>().await.unwrap();
  ```

  After:

  ```rust
  let boot = boot_test::<App>().await.unwrap();
  ```

- implement commands to manage background jobs. [https://github.com/loco-rs/loco/pull/1071](https://github.com/loco-rs/loco/pull/1071)
- magic link. [https://github.com/loco-rs/loco/pull/1085](https://github.com/loco-rs/loco/pull/1085)
- infer migration. [https://github.com/loco-rs/loco/pull/1086](https://github.com/loco-rs/loco/pull/1086)
- Remove unnecessary calls to 'register_tasks' functions in scheduler. [https://github.com/loco-rs/loco/pull/1100](https://github.com/loco-rs/loco/pull/1100)
- implement commands to manage background jobs. [https://github.com/loco-rs/loco/pull/1071](https://github.com/loco-rs/loco/pull/1071)
- expose hello_name for SMTP client config. [https://github.com/loco-rs/loco/pull/1057](https://github.com/loco-rs/loco/pull/1057)
- use reqwest with rustls rather than openssl. [https://github.com/loco-rs/loco/pull/1058](https://github.com/loco-rs/loco/pull/1058)
- more flexible config, take more values from ENV. [https://github.com/loco-rs/loco/pull/1058](https://github.com/loco-rs/loco/pull/1058)
- refactor: Use opendal to replace object_store. [https://github.com/loco-rs/loco/pull/897](https://github.com/loco-rs/loco/pull/897)
- allow override loco template. [https://github.com/loco-rs/loco/pull/1102](https://github.com/loco-rs/loco/pull/1102)
- support custom config folder. [https://github.com/loco-rs/loco/pull/1081](https://github.com/loco-rs/loco/pull/1081)
- feat: upgrade to Axum 8. [https://github.com/loco-rs/loco/pull/1130](https://github.com/loco-rs/loco/pull/1130)
- create load config hook. [https://github.com/loco-rs/loco/pull/1143](https://github.com/loco-rs/loco/pull/1143)
- initial impl new migration dsl. [https://github.com/loco-rs/loco/pull/1125](https://github.com/loco-rs/loco/pull/1125)
- allow disable limit_payload middleware. [https://github.com/loco-rs/loco/pull/1113](https://github.com/loco-rs/loco/pull/1113)

## v0.13.2

- static fallback now returns 200 and not 404 [https://github.com/loco-rs/loco/pull/991](https://github.com/loco-rs/loco/pull/991)
- cache system now has expiry [https://github.com/loco-rs/loco/pull/1006](https://github.com/loco-rs/loco/pull/1006)
- fixed: http interface binding [https://github.com/loco-rs/loco/pull/1007](https://github.com/loco-rs/loco/pull/1007)
- JWT claims now editable and public [https://github.com/loco-rs/loco/issues/988](https://github.com/loco-rs/loco/issues/988)
- CORS now not enabled in dev mode to avoid friction [https://github.com/loco-rs/loco/pull/1009](https://github.com/loco-rs/loco/pull/1009)
- fixed: task code generation now injects in all cases [https://github.com/loco-rs/loco/pull/1012](https://github.com/loco-rs/loco/pull/1012)

**BREAKING**
In your `app.rs` add the following injection comment at the bottom:

```rust
fn register_tasks(tasks: &mut Tasks) {
    tasks.register(tasks::user_report::UserReport);
    tasks.register(tasks::seed::SeedData);
    tasks.register(tasks::foo::Foo);
    // tasks-inject (do not remove)
}
```

- fix: seeding now sets autoincrement fields in the relevant DBs [https://github.com/loco-rs/loco/pull/1014](https://github.com/loco-rs/loco/pull/1014)
- fix: avoid generating entities from queue tables when the queue backend is database based [https://github.com/loco-rs/loco/issues/1013](https://github.com/loco-rs/loco/issues/1013)
- removed: channels moved to an initializer [https://github.com/loco-rs/loco/issues/892](https://github.com/loco-rs/loco/issues/892)
  **BREAKING**
  See how this looks like in [https://github.com/loco-rs/chat-rooms](https://github.com/loco-rs/chat-rooms)

## v0.13.0

- Added SQLite background job support [https://github.com/loco-rs/loco/pull/969](https://github.com/loco-rs/loco/pull/969)
- Added automatic updating of `updated_at` on change [https://github.com/loco-rs/loco/pull/962](https://github.com/loco-rs/loco/pull/962)
- fixed codegen injection point in migrations [https://github.com/loco-rs/loco/pull/952](https://github.com/loco-rs/loco/pull/952)

**NOTE: update your migration listing module like so:**

```rust
// migrations/src/lib.rs
  vec![
      Box::new(m20220101_000001_users::Migration),
      Box::new(m20231103_114510_notes::Migration),
      Box::new(m20240416_071825_roles::Migration),
      Box::new(m20240416_082115_users_roles::Migration),
      // inject-above (do not remove this comment)
  ]
```

Add the comment just before the closing array (`inject-above`)

- Added ability to name references in [https://github.com/loco-rs/loco/pull/955](https://github.com/loco-rs/loco/pull/955):

```sh
$ generate scaffold posts title:string! content:string! written_by:references:users approved_by:references:users
```

- Added hot-reload like experience to Tera templates [https://github.com/loco-rs/loco/issues/977](https://github.com/loco-rs/loco/issues/977), in debug builds only.

**NOTE: update your initializers `after_routes` like so:**

```rust
// src/initializers/view_engine.rs
async fn after_routes(&self, router: AxumRouter, _ctx: &AppContext) -> Result<AxumRouter> {
    #[allow(unused_mut)]
    let mut tera_engine = engines::TeraView::build()?;
    if std::path::Path::new(I18N_DIR).exists() {
        let arc = ArcLoader::builder(&I18N_DIR, unic_langid::langid!("en-US"))
            .shared_resources(Some(&[I18N_SHARED.into()]))
            .customize(|bundle| bundle.set_use_isolating(false))
            .build()
            .map_err(|e| Error::string(&e.to_string()))?;
        #[cfg(debug_assertions)]
        tera_engine
            .tera
            .lock()
            .expect("lock")
            .register_function("t", FluentLoader::new(arc));

        #[cfg(not(debug_assertions))]
        tera_engine
            .tera
            .register_function("t", FluentLoader::new(arc));
        info!("locales loaded");
    }

    Ok(router.layer(Extension(ViewEngine::from(tera_engine))))
}
```

- `loco doctor` now checks for app-specific minimum dependency versions. This should help in upgrades. `doctor` also supports "production only" checks which you can run in production with `loco doctor --production`. This, for example, will check your connections but will not check dependencies. [https://github.com/loco-rs/loco/pull/931](https://github.com/loco-rs/loco/pull/931)
- Use a single loco-rs dep for a whole project. [https://github.com/loco-rs/loco/pull/927](https://github.com/loco-rs/loco/pull/927)
- chore: fix generated testcase. [https://github.com/loco-rs/loco/pull/939](https://github.com/loco-rs/loco/pull/939)
- chore: Correct cargo test message. [https://github.com/loco-rs/loco/pull/938](https://github.com/loco-rs/loco/pull/938)
- Add relevant meta tags for better defaults. [https://github.com/loco-rs/loco/pull/943](https://github.com/loco-rs/loco/pull/943)
- Update cli message with correct command. [https://github.com/loco-rs/loco/pull/942](https://github.com/loco-rs/loco/pull/942)
- remove lazy_static. [https://github.com/loco-rs/loco/pull/941](https://github.com/loco-rs/loco/pull/941)
- change update HTTP verb semantics to put+patch. [https://github.com/loco-rs/loco/pull/919](https://github.com/loco-rs/loco/pull/919)
- Fixed HTML scaffold error. [https://github.com/loco-rs/loco/pull/960](https://github.com/loco-rs/loco/pull/960)
- Scaffolded HTML update method should be POST. [https://github.com/loco-rs/loco/pull/963](https://github.com/loco-rs/loco/pull/963)

## v0.12.0

This release have been primarily about cleanups and simplification.

Please update:

- `loco-rs`
- `loco-cli`

Changes:

- **generators (BREAKING)**: all prefixes in starters (e.g. `/api`) are now _local to each controller_, and generators will be prefix-aware (`--api` generator will add an `/api` prefix to controllers) [https://github.com/loco-rs/loco/pull/818](https://github.com/loco-rs/loco/pull/818)

To migrate, please move prefixes from `app.rs` to each controller you use in `controllers/`, for example in `notes` controller:

```rust
Routes::new()
    .prefix("api/notes")
    .add("/", get(list))
```

- **starters**: removed `.devcontainer` which can now be found in [loco-devcontainer](https://github.com/loco-rs/loco-devcontainer)
- **starters**: removed example `notes` scaffold (model, controllers, etc), and unified `user` and `auth` into a single file: `auth.rs`
- **generators**: `scaffold` generator will now generate a CRUD with `PUT` and `PATCH` semantics for updating an entity [https://github.com/loco-rs/loco/issues/896](https://github.com/loco-rs/loco/issues/896)
- **cleanup**: `loco-extras` was moved out of the repo, but we've incorporated `MultiDB` and `ExtraDB` from `extras` into `loco-rs` [https://github.com/loco-rs/loco/pull/917](https://github.com/loco-rs/loco/pull/917)

- `cargo loco doctor` now checks for minimal required SeaORM CLI version
- **BREAKING** Improved migration generator. If you have an existing migration project, add the following comment indicator to the top of the `vec` statement and right below the opening bracked like so in `migration/src/lib.rs`:

```rust
    fn migrations() -> Vec<Box<dyn MigrationTrait>> {
        vec![
            // inject-below (do not remove this comment)
```

## v0.11.0

- Upgrade **SeaORM to v1.1.0**
- Added OpenAPI example
- Improve health route [https://github.com/loco-rs/loco/pull/851](https://github.com/loco-rs/loco/pull/851)
- Add good pragmas to Sqlite [https://github.com/loco-rs/loco/pull/848](https://github.com/loco-rs/loco/pull/848)
- Upgrade to rsbuild 1.0. [https://github.com/loco-rs/loco/pull/792](https://github.com/loco-rs/loco/pull/792)
- Implements fmt::Debug to pub structs. [https://github.com/loco-rs/loco/pull/812](https://github.com/loco-rs/loco/pull/812)
- Add num_workers config for sidekiq queue. [https://github.com/loco-rs/loco/pull/823](https://github.com/loco-rs/loco/pull/823)
- Fix some comments in the starters and example code. [https://github.com/loco-rs/loco/pull/824](https://github.com/loco-rs/loco/pull/824)
- Fix Y2038 bug for JWT on 32 bit platforms. [https://github.com/loco-rs/loco/pull/825](https://github.com/loco-rs/loco/pull/825)
- Make App URL in Boot Banner Clickable. [https://github.com/loco-rs/loco/pull/826](https://github.com/loco-rs/loco/pull/826)
- Add `--no-banner` flag to allow disabling the banner display. [https://github.com/loco-rs/loco/pull/839](https://github.com/loco-rs/loco/pull/839)
- add on_shutdown hook. [https://github.com/loco-rs/loco/pull/842](https://github.com/loco-rs/loco/pull/842)

## v0.10.1

- `Format(respond_to): Format` extractor in controller can now be replaced with `respond_to: RespondTo` extractor for less typing.
- When supplying data to views, you can now use `data!` instead of `serde_json::json!` for shorthand.
- Refactor middlewares. [https://github.com/loco-rs/loco/pull/785](https://github.com/loco-rs/loco/pull/785). Middleware selection, configuration, and tweaking is MUCH more powerful and convenient now. You can keep the `middleware:` section empty or remove it now, see more in [the middleware docs](https://loco.rs/docs/the-app/controller/#middleware)
- **NEW (BREAKING)** background worker subsystem is now queue agnostic. Providing for both Redis and Postgres with a change of configuration. This means you can now use a full-Postgres stack to remove Redis as a dependency if you wish. Here are steps to migrate your codebase:

```rust
// in your app.rs, change the worker registration code:

// BEFORE
fn connect_workers<'a>(p: &'a mut Processor, ctx: &'a AppContext) {
    p.register(DownloadWorker::build(ctx));
}

// AFTER
async fn connect_workers(ctx: &AppContext, queue: &Queue) -> Result<()>{
    queue.register(DownloadWorker::build(ctx)).await?;
    Ok(())
}

// in your app.rs, replace the `worker` module references.
// REMOVE
worker::{AppWorker, Processor},
// REPLACE WITH
bgworker::{BackgroundWorker, Queue},

// in your workers change the signature, and add the `build` function

// BEFORE
impl worker::Worker<DownloadWorkerArgs> for DownloadWorker {
    async fn perform(&self, args: DownloadWorkerArgs) -> worker::Result<()> {

// AFTER
#[async_trait]
impl BackgroundWorker<DownloadWorkerArgs> for DownloadWorker {
    fn build(ctx: &AppContext) -> Self {
        Self { ctx: ctx.clone() }
    }
    async fn perform(&self, args: DownloadWorkerArgs) -> Result<()> {

// Finally, remove the `AppWorker` trait implementation completely.

// REMOVE
impl worker::AppWorker<DownloadWorkerArgs> for DownloadWorker {
    fn build(ctx: &AppContext) -> Self {
        Self { ctx: ctx.clone() }
    }
}
```

Finally, update your `development.yaml` and `test.yaml` with a `kind`:

```yaml
queue:
  kind: Redis # add this to the existing `queue` section
```

- **UPGRADED (BREAKING)**: `validator` crate was upgraded which require some small tweaks to work with the new API:

```rust
// BEFORE:
#[validate(custom = "validation::is_valid_email")]
pub email: String,

// AFTER:
#[validate(custom (function = "validation::is_valid_email"))]
pub email: String,
```

Then update your `Cargo.toml` to take version `0.18`:

```toml
# update
validator = { version = "0.18" }
```

- **UPGRADED (BREAKING)**: `axum-test` crate was upgraded
  Update your `Cargo.toml` to version `16`:

```toml
# update
axum-test = { version = "16" }
```

## v0.9.0

- Add fallback behavior. [https://github.com/loco-rs/loco/pull/732](https://github.com/loco-rs/loco/pull/732)
- Add Scheduler Feature for Running Cron Jobs. [https://github.com/loco-rs/loco/pull/735](https://github.com/loco-rs/loco/pull/735)
- Add `--html`, `--htmx` and `--api` flags to scaffold CLI command. [https://github.com/loco-rs/loco/pull/749](https://github.com/loco-rs/loco/pull/749)
- Add base template for scaffold generation. [https://github.com/loco-rs/loco/pull/752](https://github.com/loco-rs/loco/pull/752)
- Connect Redis only when the worker is BackgroundQueue. [https://github.com/loco-rs/loco/pull/755](https://github.com/loco-rs/loco/pull/755)
- Add loco doctor --config. [https://github.com/loco-rs/loco/pull/736](https://github.com/loco-rs/loco/pull/736)
- Rename demo: blo -> demo_app. [https://github.com/loco-rs/loco/pull/741](https://github.com/loco-rs/loco/pull/741)

## v0.8.1

- fix: introduce secondary binary for compile-and-run on Windows. [https://github.com/loco-rs/loco/pull/727](https://github.com/loco-rs/loco/pull/727)

## v0.8.0

- Added: loco-cli (`loco new`) now receives options from CLI and/or interactively asks for configuration options such as which asset pipeline, background worker type, or database provider to use.
- Fix: custom queue names now merge with default queues.
- Added `remote_ip` middleware for resolving client remote IP when under a proxy or loadbalancer, similar to the Rails `remote_ip` middleware.
- Added `secure_headers` middleware for setting secure headers by default, similar to how [https://github.com/github/secure_headers](https://github.com/github/secure_headers) works. This is now ON by default to promote security-by-default.
- Added: `money`, `blob` types to entitie generator.

## 0.7.0

- Moving to _timezone aware timestamps_. From now on migrations will generate **timestamps with time zone** by default. Moving to TZ aware timestamps in combination with newly revamped timestamp code generation in SeaORM v1.0.0 finally allows for _seamlessly_ moving between using `sqlite` and `postgres` with minimal or no entities code changes (resolved [this long standing issue](https://github.com/loco-rs/loco/issues/518#issuecomment-2051708319)). TZ aware timestamps also aligns us with how Rails works today (initially Rails had a no-tz timestamps, and today the default is to use timestamps). If not specified the TZ is the server TZ, which is usually UTC, therefore semantically this is almost like a no-tz timestamp.

**A few highlights:**

Generated entities will now always use `DateTimeWithTimeZone` for the default timestamp fields:

```
...
Generating users.rs
    > Column `created_at`: DateTimeWithTimeZone, not_null
    > Column `updated_at`: DateTimeWithTimeZone, not_null
...
```

For better cross database provider compatibility, from now on prefer the `tstz` type instead of just `ts` when using generators (i.e. `cargo loco generate model movie released:tstz`)

- remove eyer lib. [https://github.com/loco-rs/loco/pull/650](https://github.com/loco-rs/loco/pull/650)

  ### Breaking Changes:

  1.  Update the Main Function in src/bin/main

      Replace the return type of the main function:

      **Before:**

      ```rust
      async fn main() -> eyre::Result<()>
      ```

      **After:**

      ```rust
      async fn main() -> loco_rs::Result<()>
      ```

  2.  Modify examples/playground.rs
      You need to apply two changes here:

          a. Update the Function Signature
          **Before:**

          ```rust
          async fn main() -> eyre::Result<()>
          ```

          **After:**

          ```rust
          async fn main() -> loco_rs::Result<()>
          ```

          b. Adjust the Context Handling
          **Before:**

          ```rust
          let _ctx = playground::<App>().await.context("playground")?;
          ```

          **After:**

          ```rust
          let _ctx = playground::<App>().await?;
          ```

      Note,
      If you are using eyre in your project, you can continue to do so. We have only removed this crate from our base code dependencies.

- Bump rstest crate to 0.21.0. [https://github.com/loco-rs/loco/pull/650](https://github.com/loco-rs/loco/pull/650)
- Bump serial_test crate to 3.1.1. [https://github.com/loco-rs/loco/pull/651](https://github.com/loco-rs/loco/pull/651)
- Bumo object store to create to 0.10.2. [https://github.com/loco-rs/loco/pull/654](https://github.com/loco-rs/loco/pull/654)
- Bump axum crate to 0.7.5. [https://github.com/loco-rs/loco/pull/652](https://github.com/loco-rs/loco/pull/652)
- Add Hooks::before_routes to give user control over initial axum::Router construction. [https://github.com/loco-rs/loco/pull/646](https://github.com/loco-rs/loco/pull/646)
- Support logger file appender. [https://github.com/loco-rs/loco/pull/636](https://github.com/loco-rs/loco/pull/636)
- Response from the template. [https://github.com/loco-rs/loco/pull/682](https://github.com/loco-rs/loco/pull/682)
- Add get_or_insert function to cache layer. [https://github.com/loco-rs/loco/pull/637](https://github.com/loco-rs/loco/pull/637)
- Bump ORM create to 1.0.0. [https://github.com/loco-rs/loco/pull/684](https://github.com/loco-rs/loco/pull/684)

## 0.6.2

- Use Rust-based tooling for SaaS starter frontend. [https://github.com/loco-rs/loco/pull/625](https://github.com/loco-rs/loco/pull/625)
- Default binding to localhost to avoid firewall dialogues during development on macOS. [https://github.com/loco-rs/loco/pull/627](https://github.com/loco-rs/loco/pull/627)
- upgrade sea-orm to 1.0.0 RC 7. [https://github.com/loco-rs/loco/pull/627](https://github.com/loco-rs/loco/pull/639)
- Add a down migration command. [https://github.com/loco-rs/loco/pull/414](https://github.com/loco-rs/loco/pull/414)
- replace create_postgres_database function table_name to db_name. [https://github.com/loco-rs/loco/pull/647](https://github.com/loco-rs/loco/pull/647)

## 0.6.1

- Upgrade htmx generator to htmx2. [https://github.com/loco-rs/loco/pull/629](https://github.com/loco-rs/loco/pull/629)

## 0.6.0 https://github.com/loco-rs/loco/pull/610

- Bump socketioxide to v0.13.1. [https://github.com/loco-rs/loco/pull/594](https://github.com/loco-rs/loco/pull/594)
- Add CC and BCC fields to the mailers. [https://github.com/loco-rs/loco/pull/599](https://github.com/loco-rs/loco/pull/599)
- Delete reset tokens after use. [https://github.com/loco-rs/loco/pull/602](https://github.com/loco-rs/loco/pull/602)
- Generator html support delete entity. [https://github.com/loco-rs/loco/pull/604](https://github.com/loco-rs/loco/pull/604)
- **Breaking changes** move task args from BTreeMap to struct. [https://github.com/loco-rs/loco/pull/609](https://github.com/loco-rs/loco/pull/609)
  - Change task signature from `async fn run(&self, app_context: &AppContext, vars: &BTreeMap<String, String>)` to `async fn run(&self, _app_context: &AppContext, _vars: &task::Vars) -> Result<()>`
  - **Breaking changes** change default port to 5150. [https://github.com/loco-rs/loco/pull/611](https://github.com/loco-rs/loco/pull/611)
- Update shuttle version in deployment generation. [https://github.com/loco-rs/loco/pull/616](https://github.com/loco-rs/loco/pull/616)

## v0.5.0 https://github.com/loco-rs/loco/pull/593

- refactor auth middleware for supporting bearer, cookie and query. [https://github.com/loco-rs/loco/pull/560](https://github.com/loco-rs/loco/pull/560)
- SeaORM upgraded: `rc1` -> `rc4`. [https://github.com/loco-rs/loco/pull/585](https://github.com/loco-rs/loco/pull/585)
- Adding Cache to app content. [https://github.com/loco-rs/loco/pull/570](https://github.com/loco-rs/loco/pull/570)
- Apply a layer to a specific handler using `layer` method. [https://github.com/loco-rs/loco/pull/554](https://github.com/loco-rs/loco/pull/554)
- Add the debug macro to the templates to improve the errors. [https://github.com/loco-rs/loco/pull/547](https://github.com/loco-rs/loco/pull/547)
- Opentelemetry initializer. [https://github.com/loco-rs/loco/pull/531](https://github.com/loco-rs/loco/pull/531)
- Refactor auth middleware for supporting bearer, cookie and query [https://github.com/loco-rs/loco/pull/560](https://github.com/loco-rs/loco/pull/560)
- Add redirect response [https://github.com/loco-rs/loco/pull/563](https://github.com/loco-rs/loco/pull/563)
- **Breaking changes** Adding a custom claims `Option<serde_json::Value>` to the `UserClaims` struct (type changed). [https://github.com/loco-rs/loco/pull/578](https://github.com/loco-rs/loco/pull/578)
- **Breaking changes** Refactored DSL and Pagination: namespace changes. [https://github.com/loco-rs/loco/pull/566](https://github.com/loco-rs/loco/pull/566)
  - Replaced `model::query::dsl::` with `model::query`.
  - Replaced `model::query::exec::paginate` with `model::query::paginate`.
  - Updated the `PaginatedResponse` struct. Refer to its usage example [here](https://github.com/loco-rs/loco/blob/master/examples/demo/src/views/notes.rs#L29).
- **Breaking changes** When introducing the Cache system which is much more flexible than having just Redis, we now call the 'redis' member simply a 'queue' which indicates it should be used only for the internal queue and not as a general purpose cache. In the application configuration setting `redis`, change to `queue`. [https://github.com/loco-rs/loco/pull/590](https://github.com/loco-rs/loco/pull/590)

```yaml
# before:
redis:
# after:
queue:
```

- **Breaking changes** We have made a few parts of the context pluggable, such as the `storage` and new `cache` subsystems, this is why we decided to let you configure the context entirely before starting up your app. As a result, if you have a storage building hook code it should move to `after_context`, see example [here](https://github.com/loco-rs/loco/pull/570/files#diff-5534e8826fb82e5c7f2587d270a51b48009341e79889d1504e6b63b2f0b652bdR83). [https://github.com/loco-rs/loco/pull/570](https://github.com/loco-rs/loco/pull/570)

## v0.4.0

- Refactored model validation for better developer experience. Added a few traits and structs to `loco::prelude` for a smoother import story. Introducing `Validatable`:

```rust
impl Validatable for super::_entities::users::ActiveModel {
    fn validator(&self) -> Box<dyn Validate> {
        Box::new(Validator {
            name: self.name.as_ref().to_owned(),
            email: self.email.as_ref().to_owned(),
        })
    }
}

// now you can call `user.validate()` freely
```

- Refactored type field mapping to be centralized. Now model, scaffold share the same field mapping, so no more gaps like [https://github.com/loco-rs/loco/issues/513](https://github.com/loco-rs/loco/issues/513) (e.g. when calling `loco generate model title:string` the ability to map `string` into something useful in the code generation side)
  **NOTE** the `_integer` class of types are now just `_int`, e.g. `big_int`, so that it correlate with the `int` field name in a better way

- Adding to to quiery dsl `is_in` and `is_not_in`. [https://github.com/loco-rs/loco/pull/507](https://github.com/loco-rs/loco/pull/507)
- Added: in your configuration you can now use an `initializers:` section for initializer specific settings

  ```yaml
  # Initializers Configuration
  initializers:
  # oauth2:
  #   authorization_code: # Authorization code grant type
  #     - client_identifier: google # Identifier for the OAuth2 provider. Replace 'google' with your provider's name if different, must be unique within the oauth2 config.
  #       ... other fields
  ```

- Docs: fix schema data types mapping. [https://github.com/loco-rs/loco/pull/506](https://github.com/loco-rs/loco/pull/506)
- Let Result accept other errors. [https://github.com/loco-rs/loco/pull/505](https://github.com/loco-rs/loco/pull/505)
- Allow trailing slashes in URIs by adding the NormalizePathLayer. [https://github.com/loco-rs/loco/pull/481](https://github.com/loco-rs/loco/pull/481)
- **BREAKING** Move from `Result<impl IntoResponse>` to `Result<Response>`. This enables much greater flexibility building APIs, where with `Result<Response>` you mix and match response types based on custom logic (returning JSON and HTML/String in the same route).
- **Added**: mime responders similar to `respond_to` in Rails:

1. Use the `Format` extractor
2. Match on `respond_to`
3. Create different content for different response formats

The following route will always return JSON, unless explicitly asked for HTML with a
`Content-Type: text/html` (or `Accept: `) header:

```rust
pub async fn get_one(
    Format(respond_to): Format,
    Path(id): Path<i32>,
    State(ctx): State<AppContext>,
) -> Result<Response> {
    let item = load_item(&ctx, id).await?;
    match respond_to {
        RespondTo::Html => format::html(&format!("<html><body>{:?}</body></html>", item.title)),
        _ => format::json(item),
    }
}
```

## 0.3.2

- Redisgin pagination. [https://github.com/loco-rs/loco/pull/463](https://github.com/loco-rs/loco/pull/463)
- Wrap seaorm query and condition for common use cases. [https://github.com/loco-rs/loco/pull/463](https://github.com/loco-rs/loco/pull/463)
- Adding to loco-extras initializer for extra or multiple db. [https://github.com/loco-rs/loco/pull/471](https://github.com/loco-rs/loco/pull/471)
- Scaffold now supporting different templates such as API,HTML or htmx, this future is in beta.[https://github.com/loco-rs/loco/pull/474](https://github.com/loco-rs/loco/pull/474)
- Fix generatore fields types + adding tests. [https://github.com/loco-rs/loco/pull/459](https://github.com/loco-rs/loco/pull/459)
- Fix channel cors. [https://github.com/loco-rs/loco/pull/430](https://github.com/loco-rs/loco/pull/430)
- Improve auth controller compatibility with frontend [https://github.com/loco-rs/loco/pull/472](https://github.com/loco-rs/loco/pull/472)

## 0.3.1

- **Breaking changes** Upgrade sea-orm to v1.0.0-rc.1. [https://github.com/loco-rs/loco/pull/420](https://github.com/loco-rs/loco/pull/420)
  Needs to update `sea-orm` crate to use `v1.0.0-rc.1` version.
- Implemented file upload support with versatile strategies. [https://github.com/loco-rs/loco/pull/423](https://github.com/loco-rs/loco/pull/423)
- Create a `loco_extra` crate to share common basic implementations. [https://github.com/loco-rs/loco/pull/425](https://github.com/loco-rs/loco/pull/425)
- Update shuttle deployment template to 0.38. [https://github.com/loco-rs/loco/pull/422](https://github.com/loco-rs/loco/pull/422)
- Enhancement: Move the Serve to Hook flow with the ability to override default serve settings. [https://github.com/loco-rs/loco/pull/418](https://github.com/loco-rs/loco/pull/418)
- Avoid cloning sea_query::ColumnDef. [https://github.com/loco-rs/loco/pull/415](https://github.com/loco-rs/loco/pull/415)
- Allow required UUID type in a scaffold. [https://github.com/loco-rs/loco/pull/408](https://github.com/loco-rs/loco/pull/408)
- Cover `SqlxMySqlPoolConnection` in db.rs. [https://github.com/loco-rs/loco/pull/411](https://github.com/loco-rs/loco/pull/411)
- Update worker docs and change default worker mode. [https://github.com/loco-rs/loco/pull/412](https://github.com/loco-rs/loco/pull/412)
- Added server-side view generation through a new `ViewEngine` infrastructure and `Tera` server-side templates: [https://github.com/loco-rs/loco/pull/389](https://github.com/loco-rs/loco/pull/389)
- Added `generate model --migration-only` [https://github.com/loco-rs/loco/issues/400](https://github.com/loco-rs/loco/issues/400)
- Add JSON to scaffold gen. [https://github.com/loco-rs/loco/pull/396](https://github.com/loco-rs/loco/pull/396)
- Add --binding(-b) and --port(-b) to `cargo loco start`.[https://github.com/loco-rs/loco/pull/402](https://github.com/loco-rs/loco/pull/402)

## 0.2.3

- Add: support for [pre-compressed assets](https://github.com/loco-rs/loco/pull/370/files).
- Added: Support socket channels, see working example [here](https://github.com/loco-rs/chat-rooms). [https://github.com/loco-rs/loco/pull/380](https://github.com/loco-rs/loco/pull/380)
- refactor: optimize checking permissions on Postgres. [9416c](https://github.com/loco-rs/loco/commit/9416c5db85a27e3d30471374effec3fe88bf80a2)
- Added: E2E db. [https://github.com/loco-rs/loco/pull/371](https://github.com/loco-rs/loco/pull/371)

## v0.2.2

- fix: public fields in mailer-op. [e51b7e](https://github.com/loco-rs/loco/commit/e51b7e64e7667c519451ac8a8bea574b2c5d4403)
- fix: handle missing db permissions. [e51b7e](https://github.com/loco-rs/loco/commit/e51b7e64e7667c519451ac8a8bea574b2c5d4403)

## v0.2.1

- enable compression for CompressionLayer, not etag. [https://github.com/loco-rs/loco/pull/356](https://github.com/loco-rs/loco/pull/356)
- Fix nullable JSONB column schema definition. [https://github.com/loco-rs/loco/pull/357](https://github.com/loco-rs/loco/pull/357)

## v0.2.0

- Add: Loco now has Initializers ([see the docs](https://loco.rs/docs/the-app/initializers/)). Initializers help you integrate infra into your app in a seamless way, as well as share pieces of setup code between your projects
- Add: an `init_logger` hook in `src/app.rs` for those who want to take ownership of their logging and tracing stack.
- Add: Return a JSON schema when payload json could not serialize to a struct. [https://github.com/loco-rs/loco/pull/343](https://github.com/loco-rs/loco/pull/343)
- Init logger in cli.rs. [https://github.com/loco-rs/loco/pull/338](https://github.com/loco-rs/loco/pull/338)
- Add: return JSON schema in panic HTTP layer. [https://github.com/loco-rs/loco/pull/336](https://github.com/loco-rs/loco/pull/336)
- Add: JSON field support in model generation. [https://github.com/loco-rs/loco/pull/327](https://github.com/loco-rs/loco/pull/327) [https://github.com/loco-rs/loco/pull/332](https://github.com/loco-rs/loco/pull/332)
- Add: float support in model generation. [https://github.com/loco-rs/loco/pull/317](https://github.com/loco-rs/loco/pull/317)
- Fix: conflicting idx definition on M:M migration. [https://github.com/loco-rs/loco/issues/311](https://github.com/loco-rs/loco/issues/311)
- Add: **Breaking changes** Supply `AppContext` to `routes` Hook. Migration steps in `src/app.rs`:

```rust
// src/app.rs: add app context to routes function
impl Hooks for App {
  ...
  fn routes(_ctx: &AppContext) -> AppRoutes;
  ...
}
```

- Add: **Breaking changes** change parameter type from `&str` to `&Environment` in `src/app.rs`

```rust
// src/app.rs: change parameter type for `environment` from `&str` to `&Environment`
impl Hooks for App {
    ...
    async fn boot(mode: StartMode, environment: &Environment) -> Result<BootResult> {
        create_app::<Self>(mode, environment).await
    }
    ...
```

- Added: setting cookies:

```rust
format::render()
    .cookies(&[
        cookie::Cookie::new("foo", "bar"),
        cookie::Cookie::new("baz", "qux"),
    ])?
    .etag("foobar")?
    .json(notes)
```

## v0.1.9

- Adding [pagination](https://loco.rs/docs/the-app/pagination/) on Models. [https://github.com/loco-rs/loco/pull/238](https://github.com/loco-rs/loco/pull/238)
- Adding compression middleware. [https://github.com/loco-rs/loco/pull/205](https://github.com/loco-rs/loco/pull/205)
  Added support for [compression middleware](https://docs.rs/tower-http/0.5.0/tower_http/compression/index.html).
  usage:

```yaml
middlewares:
  compression:
    enable: true
```

- Create a new Database from the CLI. [https://github.com/loco-rs/loco/pull/223](https://github.com/loco-rs/loco/pull/223)
- Validate if seaorm CLI is installed before running `cargo loco db entities` and show a better error to the user. [https://github.com/loco-rs/loco/pull/212](https://github.com/loco-rs/loco/pull/212)
- Adding to `saas and `rest-api` starters a redis and DB in GitHub action workflow to allow users work with github action out of the box. [https://github.com/loco-rs/loco/pull/215](https://github.com/loco-rs/loco/pull/215)
- Adding the app name and the environment to the DB name when creating a new starter. [https://github.com/loco-rs/loco/pull/216](https://github.com/loco-rs/loco/pull/216)
- Fix generator when users adding a `created_at` or `update_at` fields. [https://github.com/loco-rs/loco/pull/214](https://github.com/loco-rs/loco/pull/214)
- Add: `format::render` which allows a builder-like formatting, including setting etag and ad-hoc headers
- Add: Etag middleware, enabled by default in starter projects. Once you set an Etag it will check for cache headers and return `304` if needed. To enable etag in your existing project:

```yaml
#...
middlewares:
  etag:
    enable: true
```

usage:

```rust
  format::render()
      .etag("foobar")?
      .json(Entity::find().all(&ctx.db).await?)
```

#### Authentication: Added API Token Authentication!

- See [https://github.com/loco-rs/loco/pull/217](https://github.com/loco-rs/loco/pull/217)
  Now when you generate a `saas starter` or `rest api` starter you will get additional authentication methods for free:

- Added: authentication added -- **api authentication** where each user has an API token in the schema, and you can authenticate with `Bearer` against that user.
- Added: authentication added -- `JWTWithUser` extractor, which is a convenience for resolving the authenticated JWT claims into a current user from database

**migrating an existing codebase**

Add the following to your generated `src/models/user.rs`:

```rust
#[async_trait]
impl Authenticable for super::_entities::users::Model {
    async fn find_by_api_key(db: &DatabaseConnection, api_key: &str) -> ModelResult<Self> {
        let user = users::Entity::find()
            .filter(users::Column::ApiKey.eq(api_key))
            .one(db)
            .await?;
        user.ok_or_else(|| ModelError::EntityNotFound)
    }

    async fn find_by_claims_key(db: &DatabaseConnection, claims_key: &str) -> ModelResult<Self> {
        super::_entities::users::Model::find_by_pid(db, claims_key).await
    }
}
```

Update imports in this file to include `model::Authenticable`:

```rust
use loco_rs::{
    auth, hash,
    model::{Authenticable, ModelError, ModelResult},
    validation,
    validator::Validate,
};
```

## v0.1.8

- Added: `loco version` for getting an operable version string containing logical crate version and git SHA if available: `0.3.0 (<git sha>)`

To migrate to this behavior from earlier versions, it requires adding the following to your `app.rs` app hooks:

```rust
    fn app_version() -> String {
        format!(
            "{} ({})",
            env!("CARGO_PKG_VERSION"),
            option_env!("BUILD_SHA")
                .or(option_env!("GITHUB_SHA"))
                .unwrap_or("dev")
        )
    }
```

Reminder: `loco --version` will give you the current Loco framework which your app was built against and `loco version` gives you your app version.

- Added: `loco generate migration` for adding ad-hoc migrations
- Added: added support in model generator for many-to-many link table generation via `loco generate model --link`
- Docs: added Migration section, added relations documentation 1:M, M:M
- Adding .devcontainer to starter projects [https://github.com/loco-rs/loco/issues/170](https://github.com/loco-rs/loco/issues/170)
- **Braking changes**: Adding `Hooks::boot` application. Migration steps:
  ```rust
  // Load boot::{create_app, BootResult, StartMode} from loco_rs lib
  // Load migration: use migration::Migrator; Only when using DB
  // Adding boot hook with the following code
  impl Hooks for App {
    ...
    async fn boot(mode: StartMode, environment: &str) -> Result<BootResult> {
      // With DB:
      create_app::<Self, Migrator>(mode, environment).await
      // Without DB:
      create_app::<Self>(mode, environment).await
    }
    ...
  }
  ```

## v0.1.7

- Added pretty backtraces [https://github.com/loco-rs/loco/issues/41](https://github.com/loco-rs/loco/issues/41)
- adding tests for note requests [https://github.com/loco-rs/loco/pull/156](https://github.com/loco-rs/loco/pull/156)
- Define the min rust version the loco can run [https://github.com/loco-rs/loco/pull/164](https://github.com/loco-rs/loco/pull/164)
- Added `cargo loco doctor` cli command for validate and diagnose configurations. [https://github.com/loco-rs/loco/pull/145](https://github.com/loco-rs/loco/pull/145)
- Added ability to specify `settings:` in config files, which are available in context
- Adding compilation mode in the banner. [https://github.com/loco-rs/loco/pull/127](https://github.com/loco-rs/loco/pull/127)
- Support shuttle deployment generator. [https://github.com/loco-rs/loco/pull/124](https://github.com/loco-rs/loco/pull/124)
- Adding a static asset middleware which allows to serve static folder/data. Enable this section in config. [https://github.com/loco-rs/loco/pull/134](https://github.com/loco-rs/loco/pull/134)
  ```yaml
  static:
    enable: true
    # ensure that both the folder.path and fallback file path are existence.
    must_exist: true
    folder:
      uri: "/assets"
      path: "frontend/dist"
    fallback: "frontend/dist/index.html"
  ```
- fix: `loco generate request` test template. [https://github.com/loco-rs/loco/pull/133](https://github.com/loco-rs/loco/pull/133)
- Improve docker deployment generator. [https://github.com/loco-rs/loco/pull/131](https://github.com/loco-rs/loco/pull/131)

## v0.1.6

- refactor: local settings are now `<env>.local.yaml` and available for all environments, for example you can add a local `test.local.yaml` and `development.local.yaml`
- refactor: removed `config-rs` and now doing config loading by ourselves.
- fix: email template rendering will not escape URLs
- Config with variables: It is now possible to use [tera](https://keats.github.io/tera) templates in config YAML files

Example of pulling a port from environment:

```yaml
server:
  port: { { get_env(name="NODE_PORT", default=5150) } }
```

It is possible to use any `tera` templating constructs such as loops, conditionals, etc. inside YAML configuration files.

- Mailer: expose `stub` in non-test

- `Hooks::before_run` with a default blank implementation. You can now code some custom loading of resources or other things before the app runs
- an LLM inference example, text generation in Rust, using an API (`examples/inference`)
- Loco starters version & create release script [https://github.com/loco-rs/loco/pull/110](https://github.com/loco-rs/loco/pull/110)
- Configure Cors middleware [https://github.com/loco-rs/loco/pull/114](https://github.com/loco-rs/loco/pull/114)
- `Hooks::after_routes` Invoke this function after the Loco routers have been constructed. This function enables you to configure custom Axum logics, such as layers, that are compatible with Axum. [https://github.com/loco-rs/loco/pull/114](https://github.com/loco-rs/loco/pull/114)
- Adding docker deployment generator [https://github.com/loco-rs/loco/pull/119](https://github.com/loco-rs/loco/pull/119)

DOCS:

- Remove duplicated docs in auth section
- FAQ docs: [https://github.com/loco-rs/loco/pull/116](https://github.com/loco-rs/loco/pull/116)

ENHANCEMENTS:

- Remove unused libs: [https://github.com/loco-rs/loco/pull/106](https://github.com/loco-rs/loco/pull/106)
- turn off default features in tokio [https://github.com/loco-rs/loco/pull/118](https://github.com/loco-rs/loco/pull/118)

## 0.1.5

NEW FEATURES

- `format:html` [https://github.com/loco-rs/loco/issues/74](https://github.com/loco-rs/loco/issues/74)
- Create a stateless HTML starter [https://github.com/loco-rs/loco/pull/100](https://github.com/loco-rs/loco/pull/100)
- Added worker generator + adding a way to test workers [https://github.com/loco-rs/loco/pull/92](https://github.com/loco-rs/loco/pull/92)

ENHANCEMENTS:

- CI: allows cargo cli run on fork prs [https://github.com/loco-rs/loco/pull/96](https://github.com/loco-rs/loco/pull/96)


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or
  advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
  address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement (open an issue to reach out).
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior,  harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.



================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Loco

Thank you for taking the time to read this.

The first way to show support is to star our repos :).


Loco is a community driven project. We welcome you to participate, contribute and together build a productivity-first web and api framework in Rust.

## Code of Conduct

This project is follows [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.

## I have a question

If you have a question to ask, feel free to open an new [discussion](https://github.com/loco-rs/loco/discussions). There are no dumb questions.

## I need a feature

Feature requests from anyone is definitely welcomed! You can open an [issue](https://github.com/loco-rs/loco/issues/new/choose). When you can, illustrate a feature with code, simulated console output, and "make believe" console interactions, so we know what you want and what you expect.

## I want to support

Awesome! The best way to support us is to recommend it to your classmates/colleagues/friends, write blog posts and tutorials on our projects and help out other users in the community.

## I want to join

We are always looking for long-term contributors. If you want to commit longer-term to Loco's open source effort, definitely talk with us!

* From time to time we will make issues clear for newcomers with `mentoring` and `good-first-issue`
* If no issue exist, just open an issue and ask how to help

### Using an example app to test

Our testing grounds is [examples/demo](examples/demo/) which is pointing to the latest local `loco` framework. You can use it to test out an actual app, using a locally modified `loco`.


## Code style

We use `rustfmt`/`cargo fmt`. A few code style options are set in the [.rustfmt.toml](.rustfmt.toml) file, and some of them are not stable yet and require a nightly version of rustfmt.

If you're using rustup, the nightly version of rustfmt can be installed by doing the following:
```sh
rustup component add rustfmt --toolchain nightly
```
And then format your code by running:
```sh
rustup default nightly

cargo fmt --all
cargo fmt --all --manifest-path loco-new/Cargo.toml

cargo clippy --fix --allow-dirty --workspace --all-features -- -D warnings -W clippy::pedantic -W clippy::nursery -W rust-2018-idioms
cargo clippy --fix --allow-dirty --workspace --all-features --manifest-path loco-new/Cargo.toml -- -D warnings -W clippy::pedantic -W clippy::nursery -W rust-2018-idioms

rustup default stable
```

## Testing

Just clone the project and run `cargo test`.
You can see how we test in [.github/workflows](.github/workflows/)

#### Snapshots
We use [insta](https://github.com/mitsuhiko/insta) for snapshot testing, which helps us detect changes in output formats and behavior. To work with snapshots:

1. Install the insta CLI tool:
```sh
cargo install cargo-insta
```

2. Run tests and review/update snapshots:
```sh
cargo insta test --review
```

For CLI-related changes, we maintain separate snapshots of binary command outputs. To update these CLI snapshots:
```sh
LOCO_CI_MODE=true TRYCMD=overwrite cargo test
```

## Docs

The documentation consists of two main components:

+ The [loco.rs website](https://loco.rs) with its source code available [here](./docs-site/).
+ RustDocs.

To reduce duplication in documentation and examples, we use [snipdoc](https://github.com/kaplanelad/snipdoc). As part of our CI process, we ensure that the documentation remains consistent.

Updating the Documentation
+ Download [snipdoc](https://github.com/kaplanelad/snipdoc).
+ Create the snippet in the [yaml file](./snipdoc.yml) or inline the code.
+ Run `snipdoc run`.

To run the documentation site locally, we use [zola](https://www.getzola.org/) so you'll need to [install](https://www.getzola.org/documentation/getting-started/installation/) it. The documentation site works with zola version `0.19.2` and since zola still has breaking changes, we make no guarantees about other versions.

Running the local preview
+ `cd docs-site`
+ `npm run serve` or `zola serve`

## Open A Pull Request

The most recommended and straightforward method to contribute changes to the project involves forking it on GitHub and subsequently initiating a pull request to propose the integration of your modifications into our repository.

Changes a starters project are not recommended. read more [here](./starters/README.md)

### In Your Pull Request Description, Include:
- References to any bugs fixed by the change
- Informative notes for the reviewer, aiding their comprehension of the necessity for the change or providing insights on how to conduct a more effective review.
- A clear explanation of how you tested your changes.

### Your PR must also:
- be based on the master branch
- adhere to the code [style](#code-style)
- Successfully passes the [test suite](#testing)


================================================
FILE: Cargo.toml
================================================
[workspace]
members = ["xtask", "loco-gen"]
exclude = ["starters"]

[workspace.package]
edition = "2021"
rust-version = "1.70"
license = "Apache-2.0"

[package]
name = "loco-rs"
version = "0.16.4"
description = "The one-person framework for Rust"
homepage = "https://loco.rs/"
documentation = "https://docs.rs/loco-rs"
repository = "https://github.com/loco-rs/loco"
license.workspace = true
edition.workspace = true
rust-version.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default = [
    "auth_jwt",
    "cli",
    "with-db",
    "cache_inmem",
    "bg_redis",
    "bg_pg",
    "bg_sqlt",
]
auth_jwt = ["dep:jsonwebtoken"]
cli = ["dep:clap"]
testing = ["dep:axum-test", "dep:scraper", "dep:tree-fs"]
with-db = [
    "dep:sea-orm",
    "dep:sea-orm-migration",
    "dep:sqlx",
    "loco-gen/with-db",
]
# Storage features
all_storage = ["storage_aws_s3", "storage_azure", "storage_gcp"]
storage_aws_s3 = ["opendal/services-s3"]
storage_azure = ["opendal/services-azblob"]
storage_gcp = ["opendal/services-gcs"]
# Cache feature
cache_inmem = ["dep:moka"]
cache_redis = ["dep:bb8-redis", "dep:bb8"]
bg_redis = ["dep:redis", "dep:ulid"]
bg_pg = ["dep:sqlx", "dep:ulid"]
bg_sqlt = ["dep:sqlx", "dep:ulid"]
## Testing feature flags
integration_test = []
# Embed assets into binary
embedded_assets = []

[dependencies]
loco-gen = { version = "0.16.1", path = "./loco-gen" }
backtrace_printer = { version = "1.3.0" }

# cli
clap = { version = "4.4.7", features = ["derive"], optional = true }
colored = { workspace = true }
sea-orm = { version = "1.1.0", features = [
    "sqlx-postgres",        # `DATABASE_DRIVER` feature
    "sqlx-sqlite",
    "runtime-tokio-rustls",
    "macros",
], optional = true }

tokio = { version = "1.45", default-features = false }
tokio-util = "0.7"
# the rest

serde = { workspace = true }
serde_json = { workspace = true }
serde_yaml = "0.9"
serde_variant = "0.1.2"
toml = "0.8"

async-trait = { workspace = true }

axum = { workspace = true }
axum-extra = { version = "0.10", features = ["cookie"] }
regex = { workspace = true }
# mailer
tera = { workspace = true }
heck = { workspace = true }
cruet = "0.13.0"
lettre = { version = "0.11.4", default-features = false, features = [
    "builder",
    "hostname",
    "smtp-transport",
    "tokio1-rustls-tls",
] }
include_dir = "0.7.3"
thiserror = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { version = "0.3.16", default-features = false, features = [
    "env-filter",
    "json",
    "ansi",
] }
tracing-appender = { version = "0.2.3", default-features = false }

duct = { workspace = true }
duct_sh = { version = "1.0.0" }

tower-http = { workspace = true }
byte-unit = "4.0.19"

argon2 = { version = "0.5", features = ["std"] }
rand = { version = "0.9", features = ["std"] }
jsonwebtoken = { version = "9.3.0", optional = true }
validator = { version = "0.20.0", features = ["derive"] }
futures-util = "0.3"
tower = { workspace = true }
bytes = "1.1"
ipnetwork = "0.20.0"
semver = "1"

axum-test = { version = "17.0.1", optional = true }
tree-fs = { version = "0.3", optional = true }

chrono = { workspace = true }

uuid = { version = "1.10.0", features = ["v4", "fast-rng"] }

# File Upload
opendal = { version = "0.54", default-features = false, features = [
    "services-memory",
    "services-fs",
] }

# cache
moka = { version = "0.12.7", features = ["sync"], optional = true }
bb8-redis = { version = "0.23", optional = true }
bb8 = { version = "0.9", optional = true }

# Scheduler
tokio-cron-scheduler = { version = "0.11.0", features = ["signal"] }
english-to-cron = { version = "0.1.2" }

# bg_sqlt: sqlite workers
# bg_pg: postgres workers
sqlx = { version = "0.8.2", default-features = false, features = [
    "json",
    "postgres",
    "chrono",
    "sqlite",
], optional = true }
ulid = { version = "1", optional = true }

# bg_redis: redis workers
redis = { version = "0.31", features = ["aio", "tokio-comp"], optional = true }

scraper = { version = "0.25.0", features = ["deterministic"], optional = true }

dashmap = "6"
notify = "8.1.0"

[workspace.dependencies]
tera = { version = "1.19.1" }
colored = { version = "3.0" }
chrono = { version = "0.4", features = ["serde"] }
tracing = "0.1.40"
regex = "1"
thiserror = "1"
serde = "1"
serde_json = "1"
async-trait = { version = "0.1.74" }
axum = { version = "0.8.1", features = ["macros", "multipart"] }
tower = "0.4"
tower-http = { version = "0.6.8", features = [
    "trace",
    "catch-panic",
    "timeout",
    "add-extension",
    "cors",
    "fs",
    "set-header",
    "compression-full",
] }
heck = "0.4.0"
duct = { version = "1.0.0" }

[dependencies.sea-orm-migration]
optional = true
version = "1.0.0"
features = [
    # Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI.
    # View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime.
    # e.g.
    "runtime-tokio-rustls", # `ASYNC_RUNTIME` feature
    "sqlx-postgres",        # `DATABASE_DRIVER` feature
    "sqlx-sqlite",
]

[package.metadata.docs.rs]
features = ["testing"]

[dev-dependencies]
loco-rs = { path = ".", features = ["testing"] }
rstest = "0.21.0"
insta = { version = "1.34.0", features = ["redactions", "yaml", "filters"] }
tree-fs = { version = "0.3" }
reqwest = { version = "0.12.7", features = ["json"] }
tower = { workspace = true, features = ["util"] }
sqlx = { version = "0.8.2", default-features = false, features = [
    "macros",
    "json",
    "postgres",
    "chrono",
    "sqlite",
    "migrate",
] }
testcontainers = { version = "0.23.3" }


================================================
FILE: DEVELOPMENT.md
================================================
## Blessed dependencies maintenance and `loco doctor`

Loco contain a few major and "blessed" dependencies, these appear **both** in an app that was generated at the surface level in their `Cargo.toml` and in the core Loco framework.

If stale, may require an upgrade as a must.

Example for such dependencies:

* The `sea-orm-cli` - while Loco uses `SeaORM`, it uses the `SeaORM` CLI to generate entities, and so there may be an incompatibility if `SeaORM` has a too large breaking change between their CLI (which ships separately) and their framework. 
* `axum`
* etc.

This is why we are checking these automatically as part of `loco doctor`.

We keep minimal version requirements for these. As a maintainer, you can update these **minimal** versions, only if required in [`doctor.rs`](src/doctor.rs).



## Running Tests

Before running tests make sure that:

[ ] redis is running
[ ] starters/saas frontend package is built:

```
$ cd starters/saas/frontend
$ npm i -g pnpm
$ pnpm i && pnpm build
```

Running all tests should be done with:

```
$ cargo xtask test
```

## Rebuilding your database and local generated entities

This should write out a fresh DB structure (drops and migrates):

```
$ cargo loco db reset
```

And then, the entities generators connect to that newly minted DB, to generate a corresponding entities code:

```
$ cargo loco db entities
```

## Publishing a new version

**Test your changes**

* [ ] Ensure you have the necessary local resources, such as `DB`/`Redis`, by executing the command `cargo loco doctor  --environment test`. In case you don't have them, refer to the relevant documentation section for guidance.
* [ ] run `cargo test` on the root to test Loco itself
* [ ] cd `examples/demo` and run `cargo test` to test our "driver app" which exercises the framework in various ways
* [ ] push your changes to Github to get the CI running and testing in various additional configurations that you don't have
* [ ] CI should pass. Take note that all `starters-*` CI are using a **fixed version** of Loco and are not seeing your changes yet


**Actually bump version + test and align starters**

* [ ] in project root, run `cargo xtask bump-version` and give it the next version. Versions are without `v` prefix. Example: `0.1.3`. 
* [ ] Did the xtask testing workflow fail?
  * [ ] YES: fix errors, and re-run `cargo xtask bump-version` **with the same version as before**.
  * [ ] NO: great, move to publishing
* [ ] Your repo may be dirty with fixes. Now that tests are passing locally commit the changes. Then run `cargo publish` to publish the next Loco version (remember: the starters at this point are pointing to the **next version already**, so we don't want to push until publish finished)
* [ ] When publish finished successfully, push your changes to github
* [ ] Wait for CI to finish. You want to be focusing more at the starters CI, because they will now pull the new version.
* [ ] Did CI fail?
  * [ ] YES: This means you had a circumstance that's not predictable (e.g. some operating system issue). Fix the issue and **repeat the bumping process, advance a new version**.
  * [ ] NO: all good! you're done.

**Book keeping**

* [ ] Update changelog: (1) move vnext to be that new version of yours, (2) create a blank vnext
* [ ] Think about if any of the items in the new version needs new documentation or update to the documentation -- and do it
## Errors

Errors are done with `thiserror`. We adopt a minimalistic approach to errors.

* We try to have _one error kind_ for the entirety of Loco.
* Errors that cannot be handled, are _informative_ and so can be opaque (we don't offer deep matching on those)
* Errors that can be handled and reasoned upon should be able to be matched and extract good knowledge from
* To users, error should _not be cryptic_, and should indicate how to fix issues as much as possible, or point to the issue precisely


### Auto conversions

When possible use `from` conversions.

```rust
    #[error(transparent)]
    JSON(#[from] serde_json::Error),
```

When complicated, implement a `From` trait yourself. This is done to _centralize_ errors into one place and not litter needless `map_err` code which holds error conversion logic (an exception is Context, see below).


### Context

When you know a user might need context, resort to manually shaping the error with extra information. First, define the error:

```rust
    #[error("cannot parse `{1}`: {0}")]
    YAMLFile(#[source] serde_yaml::Error, String),
```

Then, shape it:

```rust
  serde_yaml::from_str(&rendered)
      .map_err(|err| Error::YAMLFile(err, selected_path.to_string_lossy().to_string()))
```

In this example, the information about where `rendered` came from was long lost at the `serde_yaml::from_str` callsite. Which is why errors were cryptic indicating bad YAML format, but not where it comes from (which file).

In this case, we duplicate the YAML error type, leave one of those for auto conversions with `from`, where we don't have a file, and create a new specialized error type with the file information: `YAMLFile`.

## The `CONTRIBUTORS` comment

Some files contain a special `CONTRIBUTORS` comment. This comment should
contain context, special notes for that module, and a checklist if needed, so please make sure to follow it.



================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1.  Definitions.

    "License" shall mean the terms and conditions for use, reproduction,
    and distribution as defined by Sections 1 through 9 of this document.

    "Licensor" shall mean the copyright owner or entity authorized by
    the copyright owner that is granting the License.

    "Legal Entity" shall mean the union of the acting entity and all
    other entities that control, are controlled by, or are under common
    control with that entity. For the purposes of this definition,
    "control" means (i) the power, direct or indirect, to cause the
    direction or management of such entity, whether by contract or
    otherwise, or (ii) ownership of fifty percent (50%) or more of the
    outstanding shares, or (iii) beneficial ownership of such entity.

    "You" (or "Your") shall mean an individual or Legal Entity
    exercising permissions granted by this License.

    "Source" form shall mean the preferred form for making modifications,
    including but not limited to software source code, documentation
    source, and configuration files.

    "Object" form shall mean any form resulting from mechanical
    transformation or translation of a Source form, including but
    not limited to compiled object code, generated documentation,
    and conversions to other media types.

    "Work" shall mean the work of authorship, whether in Source or
    Object form, made available under the License, as indicated by a
    copyright notice that is included in or attached to the work
    (an example is provided in the Appendix below).

    "Derivative Works" shall mean any work, whether in Source or Object
    form, that is based on (or derived from) the Work and for which the
    editorial revisions, annotations, elaborations, or other modifications
    represent, as a whole, an original work of authorship. For the purposes
    of this License, Derivative Works shall not include works that remain
    separable from, or merely link (or bind by name) to the interfaces of,
    the Work and Derivative Works thereof.

    "Contribution" shall mean any work of authorship, including
    the original version of the Work and any modifications or additions
    to that Work or Derivative Works thereof, that is intentionally
    submitted to Licensor for inclusion in the Work by the copyright owner
    or by an individual or Legal Entity authorized to submit on behalf of
    the copyright owner. For the purposes of this definition, "submitted"
    means any form of electronic, verbal, or written communication sent
    to the Licensor or its representatives, including but not limited to
    communication on electronic mailing lists, source code control systems,
    and issue tracking systems that are managed by, or on behalf of, the
    Licensor for the purpose of discussing and improving the Work, but
    excluding communication that is conspicuously marked or otherwise
    designated in writing by the copyright owner as "Not a Contribution."

    "Contributor" shall mean Licensor and any individual or Legal Entity
    on behalf of whom a Contribution has been received by Licensor and
    subsequently incorporated within the Work.

2.  Grant of Copyright License. Subject to the terms and conditions of
    this License, each Contributor hereby grants to You a perpetual,
    worldwide, non-exclusive, no-charge, royalty-free, irrevocable
    copyright license to reproduce, prepare Derivative Works of,
    publicly display, publicly perform, sublicense, and distribute the
    Work and such Derivative Works in Source or Object form.

3.  Grant of Patent License. Subject to the terms and conditions of
    this License, each Contributor hereby grants to You a perpetual,
    worldwide, non-exclusive, no-charge, royalty-free, irrevocable
    (except as stated in this section) patent license to make, have made,
    use, offer to sell, sell, import, and otherwise transfer the Work,
    where such license applies only to those patent claims licensable
    by such Contributor that are necessarily infringed by their
    Contribution(s) alone or by combination of their Contribution(s)
    with the Work to which such Contribution(s) was submitted. If You
    institute patent litigation against any entity (including a
    cross-claim or counterclaim in a lawsuit) alleging that the Work
    or a Contribution incorporated within the Work constitutes direct
    or contributory patent infringement, then any patent licenses
    granted to You under this License for that Work shall terminate
    as of the date such litigation is filed.

4.  Redistribution. You may reproduce and distribute copies of the
    Work or Derivative Works thereof in any medium, with or without
    modifications, and in Source or Object form, provided that You
    meet the following conditions:

    (a) You must give any other recipients of the Work or
    Derivative Works a copy of this License; and

    (b) You must cause any modified files to carry prominent notices
    stating that You changed the files; and

    (c) You must retain, in the Source form of any Derivative Works
    that You distribute, all copyright, patent, trademark, and
    attribution notices from the Source form of the Work,
    excluding those notices that do not pertain to any part of
    the Derivative Works; and

    (d) If the Work includes a "NOTICE" text file as part of its
    distribution, then any Derivative Works that You distribute must
    include a readable copy of the attribution notices contained
    within such NOTICE file, excluding those notices that do not
    pertain to any part of the Derivative Works, in at least one
    of the following places: within a NOTICE text file distributed
    as part of the Derivative Works; within the Source form or
    documentation, if provided along with the Derivative Works; or,
    within a display generated by the Derivative Works, if and
    wherever such third-party notices normally appear. The contents
    of the NOTICE file are for informational purposes only and
    do not modify the License. You may add Your own attribution
    notices within Derivative Works that You distribute, alongside
    or as an addendum to the NOTICE text from the Work, provided
    that such additional attribution notices cannot be construed
    as modifying the License.

    You may add Your own copyright statement to Your modifications and
    may provide additional or different license terms and conditions
    for use, reproduction, or distribution of Your modifications, or
    for any such Derivative Works as a whole, provided Your use,
    reproduction, and distribution of the Work otherwise complies with
    the conditions stated in this License.

5.  Submission of Contributions. Unless You explicitly state otherwise,
    any Contribution intentionally submitted for inclusion in the Work
    by You to the Licensor shall be under the terms and conditions of
    this License, without any additional terms or conditions.
    Notwithstanding the above, nothing herein shall supersede or modify
    the terms of any separate license agreement you may have executed
    with Licensor regarding such Contributions.

6.  Trademarks. This License does not grant permission to use the trade
    names, trademarks, service marks, or product names of the Licensor,
    except as required for reasonable and customary use in describing the
    origin of the Work and reproducing the content of the NOTICE file.

7.  Disclaimer of Warranty. Unless required by applicable law or
    agreed to in writing, Licensor provides the Work (and each
    Contributor provides its Contributions) on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    implied, including, without limitation, any warranties or conditions
    of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
    PARTICULAR PURPOSE. You are solely responsible for determining the
    appropriateness of using or redistributing the Work and assume any
    risks associated with Your exercise of permissions under this License.

8.  Limitation of Liability. In no event and under no legal theory,
    whether in tort (including negligence), contract, or otherwise,
    unless required by applicable law (such as deliberate and grossly
    negligent acts) or agreed to in writing, shall any Contributor be
    liable to You for damages, including any direct, indirect, special,
    incidental, or consequential damages of any character arising as a
    result of this License or out of the use or inability to use the
    Work (including but not limited to damages for loss of goodwill,
    work stoppage, computer failure or malfunction, or any and all
    other commercial damages or losses), even if such Contributor
    has been advised of the possibility of such damages.

9.  Accepting Warranty or Additional Liability. While redistributing
    the Work or Derivative Works thereof, You may choose to offer,
    and charge a fee for, acceptance of support, warranty, indemnity,
    or other liability obligations and/or rights consistent with this
    License. However, in accepting such obligations, You may act only
    on Your own behalf and on Your sole responsibility, not on behalf
    of any other Contributor, and only if You agree to indemnify,
    defend, and hold each Contributor harmless for any liability
    incurred by, or claims asserted against, such Contributor by reason
    of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

Copyright [2022] Dotan Nahum, Elad Kaplan

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


================================================
FILE: README-pt_BR.md
================================================
 <div align="center">

   <img src="https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac"/>

   <h1>Bem-vindo ao Loco</h1>

   <h3>
   <!-- <snip id="description" inject_from="yaml"> -->
🚂 Loco is Rust on Rails.
<!--</snip> -->
   </h3>

   [![crate](https://img.shields.io/crates/v/loco-rs.svg)](https://crates.io/crates/loco-rs)
   [![docs](https://docs.rs/loco-rs/badge.svg)](https://docs.rs/loco-rs)
   [![Discord channel](https://img.shields.io/badge/discord-Join-us)](https://discord.gg/fTvyBzwKS8)

 </div>

[English](./README.md) · [中文](./README-zh_CN.md) · [Français](./README.fr.md) · Portuguese (Brazil) ・ [日本語](./README.ja.md) · [한국어](./README.ko.md) · [Русский](./README.ru.md) · [Español](./README.es.md)


## O que é o Loco?
`Loco` é fortemente inspirado no Rails. Se você conhece Rails e Rust, se sentirá em casa. Se você só conhece Rails e é novo em Rust, achará o Loco refrescante. Não presumimos que você conheça o Rails.

Para uma imersão mais profunda em como o Loco funciona, incluindo guias detalhados, exemplos e referências da API, confira nosso [site de documentação](https://loco.rs).


## Recursos do Loco:

* `Convenção sobre Configuração:` Semelhante ao Ruby on Rails, o Loco enfatiza simplicidade e produtividade ao reduzir a necessidade de código boilerplate. Ele utiliza padrões sensatos, permitindo que os desenvolvedores se concentrem em escrever a lógica de negócios em vez de perder tempo com configuração.

* `Desenvolvimento Rápido:` Com o objetivo de alta produtividade para o desenvolvedor, o design do Loco se concentra em reduzir código boilerplate e fornecer APIs intuitivas, permitindo que os desenvolvedores iteren rapidamente e construam protótipos com esforço mínimo.

* `Integração ORM:` Modele seu negócio com entidades robustas, eliminando a necessidade de escrever SQL. Defina relacionamentos, validações e lógica personalizada diretamente em suas entidades para melhorar a manutenção e escalabilidade.

* `Controladores:` Manipule os parâmetros de solicitações web, corpo, validação e renderize uma resposta que é consciente do conteúdo. Usamos Axum para o melhor desempenho, simplicidade e extensibilidade. Os controladores também permitem que você construa facilmente middlewares, que podem ser usados para adicionar lógica como autenticação, registro ou tratamento de erros antes de passar as solicitações para as ações principais do controlador.

* `Views:` O Loco pode se integrar com mecanismos de template para gerar conteúdo HTML dinâmico a partir de templates.

* `Trabalhos em segundo plano:` Realize trabalhos intensivos de computação ou I/O em segundo plano com uma fila baseada em Redis ou com threads. Implementar um trabalhador é tão simples quanto implementar uma função de execução para o trait Worker.

* `Scheduler:` Simplifica o tradicional e frequentemente complicado sistema crontab, tornando mais fácil e elegante agendar tarefas ou scripts shell.

* `Mailers:` Um mailer entregará e-mails em segundo plano usando a infraestrutura de trabalhador existente do loco. Tudo será transparente para você.

* `Armazenamento:` No Armazenamento do Loco, facilitamos o trabalho com arquivos por meio de várias operações. O armazenamento pode ser em memória, no disco ou utilizar serviços em nuvem, como AWS S3, GCP e Azure.

* `Cache:` O Loco fornece uma camada de cache para melhorar o desempenho da aplicação armazenando dados acessados frequentemente.

Para ver mais recursos do Loco, confira nosso [site de documentação](https://loco.rs/docs/getting-started/tour/).



## Começando
<!-- <snip id="quick-installation-command" inject_from="yaml" template="sh"> -->
```sh
cargo install loco
cargo install sea-orm-cli # Only when DB is needed
```
<!-- </snip> -->

Agora você pode criar seu novo aplicativo (escolha "`SaaS` app").


<!-- <snip id="loco-cli-new-from-template" inject_from="yaml" template="sh"> -->
```sh
❯ loco new
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · Saas App with client side rendering
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)

🚂 Loco app generated successfully in:
myapp/

- assets: You've selected `clientside` for your asset serving configuration.

Next step, build your frontend:
  $ cd frontend/
  $ npm install && npm run build
```
<!-- </snip> -->

 Agora execute `cd` no seu `myapp` e inicie seu aplicativo:
<!-- <snip id="starting-the-server-command-with-output" inject_from="yaml" template="sh"> -->
```sh
$ cargo loco start

                      ▄     ▀
                                ▀  ▄
                  ▄       ▀     ▄  ▄ ▄▀
                                    ▄ ▀▄▄
                        ▄     ▀    ▀  ▀▄▀█▄
                                          ▀█▄
▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄   ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▀▀█
██████  █████   ███ █████   ███ █████   ███ ▀█
██████  █████   ███ █████   ▀▀▀ █████   ███ ▄█▄
██████  █████   ███ █████       █████   ███ ████▄
██████  █████   ███ █████   ▄▄▄ █████   ███ █████
██████  █████   ███  ████   ███ █████   ███ ████▀
  ▀▀▀██▄ ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀ ██▀
      ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
                https://loco.rs

listening on port 5150
```
<!-- </snip> -->

## Impulsionado pelo Loco
+ [SpectralOps](https://spectralops.io) - vários serviços impulsionados pelo framework Loco
+ [Nativish](https://nativi.sh) - backend do aplicativo impulsionado pelo framework Loco

## Contribuidores ✨
Agradecimentos a essas pessoas maravilhosas:

<a href="https://github.com/loco-rs/loco/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=loco-rs/loco" />
</a>


================================================
FILE: README-zh_CN.md
================================================
 <div align="center">

   <img src="https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac"/>

   <h1>Loco</h1>


   [![crate](https://img.shields.io/crates/v/loco-rs.svg)](https://crates.io/crates/loco-rs)
   [![docs](https://docs.rs/loco-rs/badge.svg)](https://docs.rs/loco-rs)
   [![Discord channel](https://img.shields.io/badge/discord-Join-us)](https://discord.gg/fTvyBzwKS8)

 </div>

[English](./README.md) · 中文 · [Français](./README.fr.md) · [Portuguese (Brazil)](./README-pt_BR.md) ・ [日本語](./README.ja.md) · [한국어](./README.ko.md) · [Русский](./README.ru.md) · [Español](./README.es.md)

Loco 是一个用 Rust 编写的 Web 框架,类似于 Rails。Loco 提供快速构建 Web 应用的功能,并且允许创建自定义任务,可以通过 CLI 运行。

## 特性

- **简单的 API**: 使用 Rust 的强类型系统确保安全性和可靠性。
- **快速开发**: 提供快速构建 Web 应用的工具和模板。
- **CLI 支持**: 可以创建和运行自定义 CLI 任务。
- **灵活性**: 支持自定义配置和扩展。

## 安装

通过 Cargo 安装 Loco:

```sh
cargo install loco
```

## 快速开始

创建一个新的 Loco 项目:

```sh
loco new my_project
cd my_project
```

启动开发服务器:

```sh
cargo loco start
```

## 贡献

欢迎对 Loco 的贡献!请阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 了解更多信息。

## 许可证

Loco 在 MIT 许可证下发布。详情请参阅 [LICENSE](LICENSE)。

---

For more details, you can visit the [original README file](https://github.com/loco-rs/loco/blob/master/README.md).


================================================
FILE: README.es.md
================================================
<div align="center">

   <img src="https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac"/>

   <h1>Bienvenido a Loco</h1>

   <h3>
   <!-- <snip id="description" inject_from="yaml"> -->
🚂 Loco es Rust on Rails.
<!--</snip> -->
   </h3>

   [![crate](https://img.shields.io/crates/v/loco-rs.svg)](https://crates.io/crates/loco-rs)
   [![docs](https://docs.rs/loco-rs/badge.svg)](https://docs.rs/loco-rs)
   [![Discord channel](https://img.shields.io/badge/discord-Join-us)](https://discord.gg/fTvyBzwKS8)

 </div>

Español · [English](./README.md) · [中文](./README-zh_CN.md) · [Français](./README.fr.md) · [Português (Brasil)](./README-pt_BR.md) · [日本語](./README.ja.md) · [한국어](./README.ko.md) · [Русский](./README.ru.md) · Español

## ¿Qué es Loco?

`Loco` está fuertemente inspirado en Rails. Si conoces Rails y Rust, te sentirás como en casa. Si solo conoces Rails y eres nuevo en Rust, encontrarás Loco refrescante. No asumimos que conozcas Rails.

Para una explicación más profunda de cómo funciona Loco, incluyendo guías detalladas, ejemplos y referencias de la API, consulta nuestro [sitio de documentación](https://loco.rs).

## Características de Loco

* `Convención sobre configuración:` Al igual que Ruby on Rails, Loco enfatiza la simplicidad y la productividad al reducir la necesidad de código repetitivo. Utiliza valores predeterminados sensatos, permitiendo a los desarrolladores centrarse en la lógica de negocio en lugar de perder tiempo en la configuración.

* `Desarrollo rápido:` Loco está diseñado para una alta productividad del desarrollador, reduciendo el código repetitivo y proporcionando APIs intuitivas, permitiendo iterar rápidamente y construir prototipos con un esfuerzo mínimo.

* `Integración ORM:` Modela tu negocio con entidades robustas, eliminando la necesidad de escribir SQL. Define relaciones, validaciones y lógica personalizada directamente en tus entidades para una mayor mantenibilidad y escalabilidad.

* `Controladores:` Maneja parámetros de solicitudes web, cuerpo, validación y renderiza una respuesta consciente del contenido. Usamos Axum para el mejor rendimiento, simplicidad y extensibilidad. Los controladores también permiten construir middlewares fácilmente, que pueden usarse para agregar lógica como autenticación, registro o manejo de errores antes de pasar las solicitudes a las acciones principales del controlador.

* `Vistas:` Loco puede integrarse con motores de plantillas para generar contenido HTML dinámico a partir de plantillas.

* `Trabajos en segundo plano:` Realiza trabajos intensivos en computación o I/O en segundo plano con una cola respaldada por Redis o con hilos. Implementar un worker es tan simple como implementar una función perform para el trait Worker.

* `Planificador:` Simplifica el tradicional y a menudo engorroso sistema crontab, facilitando y haciendo más elegante la programación de tareas o scripts de shell.

* `Mailers:` Un mailer enviará correos electrónicos en segundo plano usando la infraestructura de background worker de Loco. Todo será transparente para ti.

* `Almacenamiento:` En Loco Storage, facilitamos el trabajo con archivos a través de múltiples operaciones. El almacenamiento puede ser en memoria, en disco o usar servicios en la nube como AWS S3, GCP y Azure.

* `Caché:` Loco proporciona una capa de caché para mejorar el rendimiento de la aplicación almacenando datos de acceso frecuente.

Para ver más características de Loco, consulta nuestro [sitio de documentación](https://loco.rs/docs/getting-started/tour/).

## Primeros pasos
<!-- <snip id="quick-installation-command" inject_from="yaml" template="sh"> -->
```sh
cargo install loco
cargo install sea-orm-cli # Solo si necesitas base de datos
```
<!-- </snip> -->

Ahora puedes crear tu nueva app (elige "`SaaS` app").

<!-- <snip id="loco-cli-new-from-template" inject_from="yaml" template="sh"> -->
```sh
❯ loco new
✔ ❯ ¿Nombre de la app? · miapp
✔ ❯ ¿Qué te gustaría construir? · App SaaS con renderizado del lado del cliente
✔ ❯ Selecciona un proveedor de BD · Sqlite
✔ ❯ Selecciona el tipo de worker en segundo plano · Async (tareas async in-process con tokio)

🚂 App Loco generada exitosamente en:
miapp/

- assets: Has seleccionado `clientside` para la configuración de tu servidor de assets.

Siguiente paso, construye tu frontend:
  $ cd frontend/
  $ npm install && npm run build
```
<!-- </snip> -->

Ahora entra en tu `miapp` y arranca tu app:
<!-- <snip id="starting-the-server-command-with-output" inject_from="yaml" template="sh"> -->
```sh
$ cargo loco start

                      ▄     ▀
                                ▀  ▄
                  ▄       ▀     ▄  ▄ ▄▀
                                    ▄ ▀▄▄
                        ▄     ▀    ▀  ▀▄▀█▄
                                          ▀█▄
▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄   ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▀▀█
██████  █████   ███ █████   ███ █████   ███ ▀█
██████  █████   ███ █████   ▀▀▀ █████   ███ ▄█▄
██████  █████   ███ █████       █████   ███ ████▄
██████  █████   ███ █████   ▄▄▄ █████   ███ █████
██████  █████   ███  ████   ███ █████   ███ ████▀
  ▀▀▀██▄ ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀ ██▀
      ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
                https://loco.rs

listening on port 5150
```
<!-- </snip> -->

## Proyectos impulsados por Loco

* [SpectralOps](https://spectralops.io) - varios servicios impulsados por el framework Loco

* [Nativish](https://nativi.sh) - backend de la app impulsado por el framework Loco

## Contribuidores ✨

Gracias a estas personas maravillosas:

<a href="https://github.com/loco-rs/loco/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=loco-rs/loco" />
</a>


================================================
FILE: README.fr.md
================================================
 <div align="center">

   <img src="https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac"/>

   <h1>Loco vous souhaite la bienvenue</h1>

   <h3>
🚂 Loco c'est Rust on Rails.
   </h3>

   [![crate](https://img.shields.io/crates/v/loco-rs.svg)](https://crates.io/crates/loco-rs)
   [![docs](https://docs.rs/loco-rs/badge.svg)](https://docs.rs/loco-rs)
   [![Discord channel](https://img.shields.io/badge/discord-Join-us)](https://discord.gg/fTvyBzwKS8)

 </div>

[English](./README.md) · [中文](./README-zh_CN.md) · Français · [Portuguese (Brazil)](./README-pt_BR.md) ・ [日本語](./README.ja.md) · [한국어](./README.ko.md) · [Русский](./README.ru.md) · [Español](./README.es.md)

## À propos de Loco
`Loco` est fortement inspiré de Rails. Si vous connaissez Rails et Rust, vous vous sentirez chez vous. Si vous ne connaissez que Rails et que vous êtes nouveau sur Rust, vous trouverez Loco rafraîchissant. Nous ne supposons pas que vous connaissez Rails.
Pour un aperçu plus approfondie du fonctionnement de Loco, y compris des guides détaillés, des exemples et des références API, consultez notre [site Web de documentation](https://loco.rs).

## Caractéristiques de Loco:

* `Convention plutôt que configuration`: Semblable à Ruby on Rails, Loco met l'accent sur la simplicité et la productivité en réduisant le besoin de code passe-partout. Il utilise des valeurs par défaut raisonnables, permettant aux développeurs de se concentrer sur l'écriture de la logique métier plutôt que de consacrer du temps à la configuration.

* `Développement rapide`: Visant une productivité élevée des développeurs, la conception de Loco se concentre sur la réduction du code passe-partout et la fourniture d'API intuitives, permettant aux développeurs d'intégrer rapidement et de créer des prototypes avec un minimum d'effort.

* `Intégration ORM`: Modélisez avec des entités robustes, éliminant le besoin d'écrire du SQL. Définissez les relations, la validation et la logique sur mesure directement sur vos entités pour une maintenabilité et une évolutivité améliorées.

* `Contrôleurs`: Gérez les paramètres et le contenu des requêtes Web, la validation des requêtes et affichez une réponse tenant compte du contenu. Nous utilisons Axum pour une meilleure performance, simplicité et extensibilité. Les contrôleurs vous permettent également de créer facilement des middlewares, qui peuvent être utilisés pour ajouter une logique telle que l'authentification, la journalisation (logging) ou la gestion des erreurs avant de transmettre les requêtes aux actions du contrôleur principal.

* `Vues`: Loco peut s'intégrer aux moteurs de _templates_ pour générer du contenu HTML dynamique à partir de modèles template.

* `Tâches en arrière-plan`: Effectuer des calculs informatiques ou d'I/O (Entrée/Sortie) intensives en arrière-plan avec une file d'attente sauvegardée Redis ou avec des threads. Implémenter un travailleur (worker) est aussi simple que d'implémenter une fonction d'exécution pour le trait Worker.

* `Scheduler`: Simplifie le système crontab traditionnel, souvent encombrant, en rendant plus facile et plus élégante la planification de tâches ou de scripts shell.

* `Mailers`: Un logiciel de messagerie enverra des e-mails en arrière-plan en utilisant l'infrastructure de travail d'arrière-plan de Loco existante. Tout se passera sans problème pour vous.

* `Stockage`: Loco Storage facilite le travail avec des fichiers via plusieurs opérations. Le stockage peut être en mémoire, sur disque ou utiliser des services cloud tels qu'AWS S3, GCP et Azure.

* `Cache :` Loco fournit une strate cache pour améliorer les performances des applications en stockant les données fréquemment consultées.

Pour en savoir plus sur les fonctionnalités de Loco, consultez notre [site Web de documentation](https://loco.rs/docs/getting-started/tour/).


## Commencez rapidement
<!-- <snip id="quick-installation-command" inject_from="yaml" template="sh"> -->
```sh
cargo install loco
cargo install sea-orm-cli # Only when DB is needed
```
<!-- </snip> -->

Vous pouvez maintenant créer votre nouvelle application (choisissez "`SaaS` app").


<!-- <snip id="loco-cli-new-from-template" inject_from="yaml" template="sh"> -->
```sh
❯ loco new
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · Saas App with client side rendering
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)

🚂 Loco app generated successfully in:
myapp/

- assets: You've selected `clientside` for your asset serving configuration.

Next step, build your frontend:
  $ cd frontend/
  $ npm install && npm run build
```
<!-- </snip> -->

Maintenant, faite `cd` dans votre `myapp` et démarrez votre application:

<!-- <snip id="starting-the-server-command-with-output" inject_from="yaml" template="sh"> -->
```sh
$ cargo loco start

                      ▄     ▀
                                ▀  ▄
                  ▄       ▀     ▄  ▄ ▄▀
                                    ▄ ▀▄▄
                        ▄     ▀    ▀  ▀▄▀█▄
                                          ▀█▄
▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄   ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▀▀█
██████  █████   ███ █████   ███ █████   ███ ▀█
██████  █████   ███ █████   ▀▀▀ █████   ███ ▄█▄
██████  █████   ███ █████       █████   ███ ████▄
██████  █████   ███ █████   ▄▄▄ █████   ███ █████
██████  █████   ███  ████   ███ █████   ███ ████▀
  ▀▀▀██▄ ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀ ██▀
      ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
                https://loco.rs

listening on port 5150
```
<!-- </snip> -->

## Servi par Loco
+ [SpectralOps](https://spectralops.io) - divers services servi par le framework Loco
+ [Nativish](https://nativi.sh) - app backend servi par le framework Loco

## Contributeurs ✨
Merci à ces personnes formidables :

<a href="https://github.com/loco-rs/loco/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=loco-rs/loco" />
</a>



================================================
FILE: README.ja.md
================================================
<div align="center">

   <img src="https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac"/>

   <h1>Locoへようこそ</h1>

   <h3>
🚂 LocoはRust on Railsです。
   </h3>

   [![crate](https://img.shields.io/crates/v/loco-rs.svg)](https://crates.io/crates/loco-rs)
   [![docs](https://docs.rs/loco-rs/badge.svg)](https://docs.rs/loco-rs)
   [![Discord channel](https://img.shields.io/badge/discord-Join-us)](https://discord.gg/fTvyBzwKS8)

 </div>

English · [中文](./README-zh_CN.md) · [Français](./README.fr.md) · [Portuguese (Brazil)](./README-pt_BR.md) ・ 日本語 · [한국어](./README.ko.md) · [Русский](./README.ru.md)

## Locoとは?
`Loco`はRailsに強くインスパイアされています。RailsとRustの両方を知っているなら、すぐに馴染むでしょう。Railsしか知らなく、Rustに新しい方でも、Locoは新鮮に感じるでしょう。Railsを知っているとは仮定していません。

Locoの動作についての詳細なガイド、例、APIリファレンスは、[ドキュメント](https://loco.rs)をチェックしてください。

## Locoの特徴:

* `設定より規約:` Ruby on Railsに似て、Locoはボイラープレートコードを減らすことでシンプルさと生産性を発揮します。合理的なデフォルトを使用し、開発者が設定に時間を費やすのではなく、ビジネスロジックの記述に集中できるようにします。

* `迅速な開発:` 高い開発者生産性を目指し、Locoの設計はボイラープレートコードを減らし、直感的なAPIを提供することに焦点を当てています。これにより、開発者は迅速に反復し、最小限の努力でプロトタイプを構築できます。

* `ORM統合:` ビジネスモデルを堅牢なエンティティで表現し、SQLを書く必要をなくします。エンティティに直接関係、検証、およびカスタムロジックを定義でき、メンテナンス性とスケーラビリティが向上します。

* `コントローラー:` ウェブリクエストのパラメータ、ボディ、検証を処理し、コンテンツに応じたレスポンスをレンダリングします。最高のパフォーマンス、シンプルさ、拡張性のためにAxumを使用しています。コントローラーは、認証、ロギング、エラーハンドリングなどのロジックを追加するためのミドルウェアを簡単に構築できます。

* `ビュー:` Locoはテンプレートエンジンと統合し、テンプレートから動的なHTMLコンテンツを生成できます。

* `バックグラウンドジョブ:` Redisバックエンドキューやスレッドを使用して、計算またはI/O集約型のジョブをバックグラウンドで実行します。ワーカーを実装するのは、Workerトレイトのperform関数を実装するだけです。

* `スケジューラー:` 従来の、しばしば面倒なcrontabシステムを簡素化し、タスクやシェルスクリプトをスケジュールするのをより簡単かつエレガントにします。

* `メール送信:` メール送信者は、既存のLocoバックグラウンドワーカーインフラストラクチャを使用して、バックグラウンドでメールを配信します。すべてがシームレスに行われます。

* `ストレージ:` Locoのストレージでは、ファイル操作を簡素化します。ストレージはメモリ内、ディスク上、またはAWS S3、GCP、Azureなどのクラウドサービスを使用できます。

* `キャッシュ:` Locoは、頻繁にアクセスされるデータを保存することでアプリケーションのパフォーマンスを向上させるためのキャッシュレイヤーを提供します。

Locoの詳細な機能については、[ドキュメントウェブサイト](https://loco.rs/docs/getting-started/tour/)を確認してください。

## 始め方
```sh
cargo install loco
cargo install sea-orm-cli # データベースが必要な場合のみ
```

以下で新しいアプリを作成できます(「`SaaS`アプリ」を選択)。

```sh
❯ loco new
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · SaaS app (with DB and user auth)
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)
✔ ❯ Select an asset serving configuration · Client (configures assets for frontend serving)

🚂 Loco app generated successfully in:
myapp/
```

次に`myapp`に移動し、アプリを起動します:
```sh
$ cargo loco start

                      ▄     ▀
                                ▀  ▄
                  ▄       ▀     ▄  ▄ ▄▀
                                    ▄ ▀▄▄
                        ▄     ▀    ▀  ▀▄▀█▄
                                          ▀█▄
▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄   ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▀▀█
██████  █████   ███ █████   ███ █████   ███ ▀█
██████  █████   ███ █████   ▀▀▀ █████   ███ ▄█▄
██████  █████   ███ █████       █████   ███ ████▄
██████  █████   ███ █████   ▄▄▄ █████   ███ █████
██████  █████   ███  ████   ███ █████   ███ ████▀
  ▀▀▀██▄ ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀ ██▀
      ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
                https://loco.rs

listening on port 5150
```

## Locoによって開発されています
+ [SpectralOps](https://spectralops.io) - Locoフレームワークによる各種サービス
+ [Nativish](https://nativi.sh) - Locoフレームワークによるアプリバックエンド

## 貢献者 ✨
これらの素晴らしい人々に感謝します:

<a href="https://github.com/loco-rs/loco/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=loco-rs/loco" />
</a>


================================================
FILE: README.ko.md
================================================
 <div align="center">

   <img src="https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac"/>

   <h1>Loco에 오신 것을 환영합니다</h1>

   <h3>
   🚂 Loco는 Rust on Rails입니다.
   </h3>

   [![crate](https://img.shields.io/crates/v/loco-rs.svg)](https://crates.io/crates/loco-rs)
   [![docs](https://docs.rs/loco-rs/badge.svg)](https://docs.rs/loco-rs)
   [![Discord channel](https://img.shields.io/badge/discord-Join-us)](https://discord.gg/fTvyBzwKS8)

 </div>

[English](./README.md) · [中文](./README-zh_CN.md) · [Français](./README.fr.md) · [Portuguese (Brazil)](./README-pt_BR.md) ・ [日本語](./README.ja.md) · 한국어 · [Русский](./README.ru.md) · [Español](./README.es.md)


## Loco란?
`Loco`는 Rails에서 강한 영감을 받았습니다. Rails와 Rust를 모두 알고 계신다면 친숙하게 느껴지실 것이며, Rails만 알고 Rust를 처음 접하시는 분들에게도 Loco는 새롭게 다가올 것입니다. 참고로, Rails에 대한 사전 지식은 필수가 아닙니다.

Loco의 작동 방식에 대해 더 자세히 알아보려면 가이드, 예제, API 참조를 포함한 [문서 웹사이트](https://loco.rs)를 확인해보세요.

## Loco의 주요 기능:

* `설정보다 관습`: Ruby on Rails와 유사하게, Loco는 상용구 코드의 필요성을 줄임으로써 단순성과 생산성을 강조합니다. 합리적인 기본값을 사용하여 개발자가 설정보다는 비즈니스 로직 작성에 집중할 수 있게 합니다.

* `빠른 개발`: 높은 개발자 생산성을 목표로 하며, Loco의 설계는 상용구 코드를 줄이고 직관적인 API를 제공하여 개발자가 최소한의 노력으로 빠르게 반복하고 프로토타입을 구축할 수 있도록 합니다.

* `ORM 통합`: SQL 작성 없이 비즈니스를 강력한 엔티티로 모델링합니다. 관계, 유효성 검사, 사용자 정의 로직을 엔티티에 직접 정의하여 유지보수성과 확장성을 향상시킵니다.

* `컨트롤러`: 웹 요청 매개변수, 본문, 유효성 검사를 처리하고 컨텐츠를 인식하는 응답을 렌더링합니다. 최고의 성능, 단순성, 확장성을 위해 Axum을 사용합니다. 또한 컨트롤러를 통해 인증, 로깅, 오류 처리와 같은 로직을 추가할 수 있는 미들웨어를 쉽게 구축할 수 있습니다.

* `뷰`: Loco는 템플릿에서 동적 HTML 콘텐츠를 생성하기 위해 템플릿 엔진과 통합할 수 있습니다.

* `백그라운드 작업`: Redis 기반 큐 또는 스레드를 사용하여 계산이나 I/O 집약적인 작업을 백그라운드에서 수행합니다. Worker 트레이트에 대한 perform 함수를 구현하는 것만으로도 워커를 구현할 수 있습니다.

* `스케줄러`: 전통적이고 번거로운 crontab 시스템을 단순화하여 작업이나 셸 스크립트를 더 쉽고 우아하게 예약할 수 있습니다.

* `메일러`: 메일러는 기존 loco 백그라운드 워커 인프라를 사용하여 이메일을 백그라운드에서 전달합니다. 모든 과정이 매끄럽게 처리됩니다.

* `스토리지`: Loco 스토리지는 여러 작업을 통해 파일 작업을 용이하게 합니다. 메모리 내, 디스크, AWS S3, GCP, Azure와 같은 클라우드 서비스를 사용할 수 있습니다.

* `캐시`: Loco는 자주 접근하는 데이터를 저장하여 애플리케이션 성능을 향상시키는 캐시 레이어를 제공합니다.

더 많은 Loco 기능을 보려면 [문서 웹사이트](https://loco.rs/docs/getting-started/tour/)를 확인하세요.


## 시작하기
<!-- <snip id="quick-installation-command" inject_from="yaml" template="sh"> -->
```sh
cargo install loco
cargo install sea-orm-cli # Only when DB is needed
```
<!-- </snip> -->

이제 새로운 앱을 만들 수 있습니다 ("`SaaS 앱`" 선택).


<!-- <snip id="loco-cli-new-from-template" inject_from="yaml" template="sh"> -->
```sh
❯ loco new
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · Saas App with client side rendering
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)

🚂 Loco app generated successfully in:
myapp/

- assets: You've selected `clientside` for your asset serving configuration.

Next step, build your frontend:
  $ cd frontend/
  $ npm install && npm run build
```
<!-- </snip> -->

이제 `myapp` 디렉토리로 이동하여 앱을 시작하세요:

<!-- <snip id="starting-the-server-command-with-output" inject_from="yaml" template="sh"> -->
```sh
$ cargo loco start

                      ▄     ▀
                                ▀  ▄
                  ▄       ▀     ▄  ▄ ▄▀
                                    ▄ ▀▄▄
                        ▄     ▀    ▀  ▀▄▀█▄
                                          ▀█▄
▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄   ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▀▀█
██████  █████   ███ █████   ███ █████   ███ ▀█
██████  █████   ███ █████   ▀▀▀ █████   ███ ▄█▄
██████  █████   ███ █████       █████   ███ ████▄
██████  █████   ███ █████   ▄▄▄ █████   ███ █████
██████  █████   ███  ████   ███ █████   ███ ████▀
  ▀▀▀██▄ ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀ ██▀
      ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
                https://loco.rs

listening on port 5150
```
<!-- </snip> -->

## Loco 사용 사례
+ [SpectralOps](https://spectralops.io) - Loco 프레임워크로 구동되는 다양한 서비스
+ [Nativish](https://nativi.sh) - Loco 프레임워크로 구동되는 앱 백엔드

## 기여자 ✨
이 멋진 분들께 감사드립니다:

<a href="https://github.com/loco-rs/loco/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=loco-rs/loco" />
</a>


================================================
FILE: README.md
================================================
 <div align="center">

   <img src="https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac"/>

   <h1>Welcome to Loco</h1>

   <h3>
   <!-- <snip id="description" inject_from="yaml"> -->
🚂 Loco is Rust on Rails.
<!--</snip> -->
   </h3>

   [![crate](https://img.shields.io/crates/v/loco-rs.svg)](https://crates.io/crates/loco-rs)
   [![docs](https://docs.rs/loco-rs/badge.svg)](https://docs.rs/loco-rs)
   [![Discord channel](https://img.shields.io/badge/discord-Join-us)](https://discord.gg/fTvyBzwKS8)

 </div>


English · [中文](./README-zh_CN.md) · [Français](./README.fr.md) · [Portuguese (Brazil)](./README-pt_BR.md) ・ [日本語](./README.ja.md) · [한국어](./README.ko.md) · [Русский](./README.ru.md) · [Español](./README.es.md)


## What's Loco?
`Loco` is strongly inspired by Rails. If you know Rails and Rust, you'll feel at home. If you only know Rails and new to Rust, you'll find Loco refreshing. We do not assume you know Rails.

For a deeper dive into how Loco works, including detailed guides, examples, and API references, check out our [documentation website](https://loco.rs).


## Features of Loco:

* `Convention Over Configuration:` Similar to Ruby on Rails, Loco emphasizes simplicity and productivity by reducing the need for boilerplate code. It uses sensible defaults, allowing developers to focus on writing business logic rather than spending time on configuration.

* `Rapid Development:` Aim for high developer productivity, Loco’s design focuses on reducing boilerplate code and providing intuitive APIs, allowing developers to iterate quickly and build prototypes with minimal effort.

* `ORM Integration:` Model your business with robust entities, eliminating the need to write SQL. Define relationships, validation, and custom logic directly on your entities for enhanced maintainability and scalability.

* `Controllers`: Handle web requests parameters, body, validation, and render a response that is content-aware. We use Axum for the best performance, simplicity, and extensibility. Controllers also allow you to easily build middlewares, which can be used to add logic such as authentication, logging, or error handling before passing requests to the main controller actions.

* `Views:` Loco can integrate with templating engines to generate dynamic HTML content from templates.

* `Background Jobs:` Perform compute or I/O intensive jobs in the background with a Redis backed queue, or with threads. Implementing a worker is as simple as implementing a perform function for the Worker trait.

* `Scheduler:` Simplifies the traditional, often cumbersome crontab system, making it easier and more elegant to schedule tasks or shell scripts.

* `Mailers:` A mailer will deliver emails in the background using the existing loco background worker infrastructure. It will all be seamless for you.

* `Storage:` In Loco Storage, we facilitate working with files through multiple operations. Storage can be in-memory, on disk, or use cloud services such as AWS S3, GCP, and Azure.

* `Cache:` Loco provides an cache layer to improve application performance by storing frequently accessed data.

So see more Loco features, check out our [documentation website](https://loco.rs/docs/getting-started/tour/).



## Getting Started
<!-- <snip id="quick-installation-command" inject_from="yaml" template="sh"> -->
```sh
cargo install loco
cargo install sea-orm-cli # Only when DB is needed
```
<!-- </snip> -->

Now you can create your new app (choose "`SaaS` app").


<!-- <snip id="loco-cli-new-from-template" inject_from="yaml" template="sh"> -->
```sh
❯ loco new
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · Saas App with client side rendering
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)

🚂 Loco app generated successfully in:
myapp/

- assets: You've selected `clientside` for your asset serving configuration.

Next step, build your frontend:
  $ cd frontend/
  $ npm install && npm run build
```
<!-- </snip> -->

 Now `cd` into your `myapp` and start your app:
<!-- <snip id="starting-the-server-command-with-output" inject_from="yaml" template="sh"> -->
```sh
$ cargo loco start

                      ▄     ▀
                                ▀  ▄
                  ▄       ▀     ▄  ▄ ▄▀
                                    ▄ ▀▄▄
                        ▄     ▀    ▀  ▀▄▀█▄
                                          ▀█▄
▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄   ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▀▀█
██████  █████   ███ █████   ███ █████   ███ ▀█
██████  █████   ███ █████   ▀▀▀ █████   ███ ▄█▄
██████  █████   ███ █████       █████   ███ ████▄
██████  █████   ███ █████   ▄▄▄ █████   ███ █████
██████  █████   ███  ████   ███ █████   ███ ████▀
  ▀▀▀██▄ ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀ ██▀
      ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
                https://loco.rs

listening on port 5150
```
<!-- </snip> -->

## Powered by Loco
+ [SpectralOps](https://spectralops.io) - various services powered by Loco
  framework
+ [Nativish](https://nativi.sh) - app backend powered by Loco framework

## Contributors ✨
Thanks goes to these wonderful people:

<a href="https://github.com/loco-rs/loco/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=loco-rs/loco" />
</a>


================================================
FILE: README.ru.md
================================================
 <div align="center">

   <img src="https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac"/>

   <h1>Добро пожаловать в *Loco*</h1>

   <h3>
   <!-- <snip id="description" inject_from="yaml"> -->
🚂 Loco is Rust on Rails.
<!--</snip> -->
   </h3>

   [![crate](https://img.shields.io/crates/v/loco-rs.svg)](https://crates.io/crates/loco-rs)
   [![docs](https://docs.rs/loco-rs/badge.svg)](https://docs.rs/loco-rs)
   [![Discord channel](https://img.shields.io/badge/discord-Join-us)](https://discord.gg/fTvyBzwKS8)

 </div>

[English](./README.md) · [中文](./README-zh_CN.md) · [Français](./README.fr.md) · [Portuguese (Brazil)](./README-pt_BR.md) ・ [日本語](./README.ja.md) · Русский · [Español](./README.es.md)


## Что такое Loco?
*Loco* сильно вдохновлён проектом *Ruby on Rails*. Если вы знакомы и с *Rails*, и с *Rust*, вы будете чувствовать себя как дома. Если вы знаете только *Rails*, и не знакомы с *Rust*, *Loco* будет для вас чем-то освежающим.

Если вам интересно узнать внутрение устройство *Loco*, включая детальные гайды, примеры, и устройство API, почитайте нашу [документацию](https://loco.rs).


## Фишки Loco:

- **Простота превыше конфигурации**: Подобно *Ruby on Rails*, *Loco* делает упор на простоту и продуктивность, снижая потребность в лишнем коде. *Loco* использует оптимальные настройки по-умолчанию, давая разработчикам возможность сфокусироваться на написании бизнес логики, а не конфигурации.
- **Быстрая разработка**: Ставя акцент на высокой производительности разработчика, Дизайн *Loco* фокусируется на сокращении ненужного кода и предоставления интуитивного API. Это позволяет быстро создавать прототипы без лишних усилий.
- **ORM интеграция**: Стройте свой бизнес с крепкими составляющими, убирая необходимость писать SQL. Определяйте взаимосвязи, проверку, и кастомную логику прямо в составляющих, упрощая поддержку и рост кодовой базы.
- **Контролеры**: Обрабатывайте параметры и данные web-запросов, проверяйте их содержимое, отображайте ответ с учетом запроса. Мы используем *Axum* для достижения наилучшей производительности, простоты, и возможности расширения. Также, контролеры облегчают внедрение middleware. Это может быть использовано для добавления всевозможной логики: аутентификации, логгинга, или обработки ошибок перед отправкой на сервер.
- **Виды**: *Loco* может интегрироваться с template-движками для генерации динамического HTML из шаблонов.
- **Фоновые задачи**: Исполняйте I/O и другие тяжелые операции в фоновом режиме с помощью *Redis*, или потоков. Для написания функционала фоновой задачи нужно всего лишь написать функцию `perform` из `trait Worker`.
- **Планировщик**: Облегчает традиционную, часто громоздкую систему, упрощая планировку задач и исполнение shell-скриптов.
- **Отправка электронной почты**: Отправка электронной почты в фоновом режиме, без необходимости создавать новую фоновую задачу.
- **Хранилище**: Мы способствуем работе с файлами несколькими путями: хранение в памяти, на диске, или использование облачных сервисов как *AWS*, *S3*, *GCP*, и *Azure*.
- **Кэширование**: *Loco* кэширует частые запросы для улучшения производительности приложения.

У *Loco* есть ещё множество фишек, котрые вы можете посмотреть на [сайте документации](https://loco.rs/docs/getting-started/tour/).


## Установка
<!-- <snip id="quick-installation-command" inject_from="yaml" template="sh"> -->
```sh
cargo install loco
cargo install sea-orm-cli # Only when DB is needed
```
<!-- </snip> -->

Теперь вы можете создать свое новое приложение (выберете "`SaaS` app").


<!-- <snip id="loco-cli-new-from-template" inject_from="yaml" template="sh"> -->
```sh
❯ loco new
✔ ❯ App name? · myapp
✔ ❯ What would you like to build? · Saas App with client side rendering
✔ ❯ Select a DB Provider · Sqlite
✔ ❯ Select your background worker type · Async (in-process tokio async tasks)

🚂 Loco app generated successfully in:
myapp/

- assets: You've selected `clientside` for your asset serving configuration.

Next step, build your frontend:
  $ cd frontend/
  $ npm install && npm run build
```
<!-- </snip> -->

Теперь выполните `cd` в папку `myapp` и запускайте приложение:
<!-- <snip id="starting-the-server-command-with-output" inject_from="yaml" template="sh"> -->
```sh
$ cargo loco start

                      ▄     ▀
                                ▀  ▄
                  ▄       ▀     ▄  ▄ ▄▀
                                    ▄ ▀▄▄
                        ▄     ▀    ▀  ▀▄▀█▄
                                          ▀█▄
▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄   ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▀▀█
██████  █████   ███ █████   ███ █████   ███ ▀█
██████  █████   ███ █████   ▀▀▀ █████   ███ ▄█▄
██████  █████   ███ █████       █████   ███ ████▄
██████  █████   ███ █████   ▄▄▄ █████   ███ █████
██████  █████   ███  ████   ███ █████   ███ ████▀
  ▀▀▀██▄ ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀ ██▀
      ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
                https://loco.rs

listening on port 5150
```
<!-- </snip> -->

## Проекты, использующие *Loco*
+ [SpectralOps](https://spectralops.io) - различные сервисы, использующие *Loco*
  framework
+ [Nativish](https://nativi.sh) - backend приложения, использующий *Loco*

## Контрибьютеры ✨
Спасибо всем этим прекрасным людям:

<a href="https://github.com/loco-rs/loco/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=loco-rs/loco" />
</a>


================================================
FILE: SECURITY.md
================================================
# Security Policy

By researching and submitting a vulnerability, you'll be helping open source and this project's goal to provide a fast to build fast to run Web framework based on Rust.


## Reporting a Vulnerability

Please report directly to [dotan@rng0.io](mailto:dotan@rng0.io).

We will credit you as a committer with every vulnerability you find that we can validate.


================================================
FILE: build/embedded_assets.rs
================================================
use std::collections::{HashMap, HashSet};
use std::{
    env,
    fs::{self, File},
    io::{self, Write},
    path::{Path, PathBuf},
};

pub fn build_static_assets(out_dir: &Path) {
    // Determine the application root directory using Cargo environment variables
    let Some(app_dir) = find_app_directory(out_dir) else {
        eprintln!("Error: Could not determine application directory");
        return;
    };

    let app_dir_str = app_dir.to_string_lossy().to_string();

    println!("cargo:warning=Building with embedded_assets feature");
    println!("cargo:warning=Application directory: {app_dir_str}");
    println!("cargo:warning=Assets will only be loaded from the application directory");
    println!("cargo:rerun-if-changed={app_dir_str}/assets/");
    println!("cargo:rerun-if-changed={app_dir_str}/src/assets/");
    // Also run build script again if the build files change
    println!("cargo:rerun-if-changed=build/embedded_assets.rs");

    let generated_path = out_dir.join("generated_code");

    // Create the directory if it doesn't exist
    if let Err(e) = fs::create_dir_all(&generated_path) {
        eprintln!("Warning: Could not create directory: {e}");
        return;
    }

    // Only search in the application directory
    let app_root = app_dir;

    // Find all directories recursively, without filtering by name
    let all_dirs = discover_all_directories(&app_root.join("assets"));

    println!("cargo:warning=Discovered directories for assets:");
    for dir in &all_dirs {
        println!("cargo:warning=  - {}", dir.display());
    }

    // Single collection for all files
    let mut all_files = HashMap::new();

    // Store the assets directory reference to pass to collect_all_files
    let assets_dir = app_root.join("assets");

    // Process all discovered directories
    for dir in &all_dirs {
        // Process all files in this directory
        collect_all_files(dir, &assets_dir, &mut all_files);
    }

    // Generate code for all assets
    if all_files.is_empty() {
        println!("cargo:warning=No asset files found");
        // Generate empty asset files if no files found
        if let Err(e) = generate_empty_asset_files(&generated_path) {
            eprintln!("Warning: Failed to generate empty asset files: {e}");
        }
    } else {
        println!("cargo:warning=Found {} asset files", all_files.len());
        if let Err(e) = generate_asset_code(&all_files, &generated_path) {
            eprintln!("Warning: Failed to generate asset code: {e}");
        }
    }
}

pub fn find_app_directory(out_dir: &Path) -> Option<PathBuf> {
    // Find project root from OUT_DIR by going up to parent of "target" directory
    let mut path = out_dir.to_path_buf();
    while path.pop() {
        if path.file_name().and_then(|n| n.to_str()) == Some("target") && path.pop() {
            return Some(path);
        }

        // Safety check
        if path.as_os_str().is_empty() {
            break;
        }
    }

    // Fallback to current directory
    env::current_dir().ok()
}

pub fn discover_all_directories(app_root: &Path) -> Vec<PathBuf> {
    let mut directories = Vec::new();
    let mut visited = HashSet::new();

    // Only include the directory if it exists
    if app_root.exists() {
        // Add the root directory itself
        directories.push(app_root.to_path_buf());

        // Start recursive discovery
        recursively_collect_directories(app_root, &mut directories, &mut visited);
    }

    // Sort directories by their string representation to ensure consistent ordering
    directories.sort_by(|a, b| {
        a.to_string_lossy()
            .to_string()
            .cmp(&b.to_string_lossy().to_string())
    });

    directories
}

pub fn recursively_collect_directories(
    dir: &Path,
    directories: &mut Vec<PathBuf>,
    visited: &mut std::collections::HashSet<PathBuf>,
) {
    // Check if we've already visited this directory
    if !visited.insert(dir.to_path_buf()) {
        return;
    }

    // Continue recursively discovering subdirectories
    if let Ok(entries) = fs::read_dir(dir) {
        for entry in entries.flatten() {
            let path = entry.path();

            if path.is_dir() {
                // Add this directory to our list
                directories.push(path.clone());
                // Continue recursion
                recursively_collect_directories(&path, directories, visited);
            }
        }
    }
}

pub fn collect_all_files(dir: &Path, assets_dir: &Path, all_files: &mut HashMap<String, String>) {
    if let Ok(entries) = fs::read_dir(dir) {
        for entry in entries.flatten() {
            let path = entry.path();

            if path.is_file() {
                // Skip if we can't determine the file path or extension
                let full_path = path.to_string_lossy().to_string();

                // Create a relative path based on the assets directory
                let Ok(rel_path) = path.strip_prefix(assets_dir) else {
                    println!(
                        "cargo:warning=Failed to strip prefix for path: {}",
                        path.display()
                    );
                    continue; // Skip this file if we can't determine its relative path
                };

                // Format the key as a path, using forward slashes
                let mut key = format!("/{}", rel_path.to_string_lossy().replace('\\', "/"));

                // Remove any double slashes
                key = key.replace("//", "/");

                // Special handling for templates in views directory
                if key.starts_with("/views/") {
                    // For templates, we want to:
                    // 1. Strip "/views/" prefix for proper Tera template inheritance
                    // 2. Keep the relative path structure for nested templates
                    key = key.trim_start_matches("/views/").to_string();
                }

                // Log what we found
                println!("cargo:warning=Found asset: {} -> {}", path.display(), key);

                // Store the file
                all_files.insert(full_path, key);
            }
        }
    }
}

#[allow(clippy::too_many_lines)]
pub fn generate_asset_code(
    all_files: &HashMap<String, String>,
    output_path: &Path,
) -> io::Result<()> {
    // Create vectors to track which files go where
    let mut static_assets = Vec::new();
    let mut template_files = Vec::new();

    // Simple categorization: if file ends with .html or .htm, it's a template, otherwise static asset
    for (path, key) in all_files {
        if std::path::Path::new(key)
            .extension()
            .is_some_and(|ext| ext.eq_ignore_ascii_case("html"))
            || std::path::Path::new(key)
                .extension()
                .is_some_and(|ext| ext.eq_ignore_ascii_case("htm"))
        {
            template_files.push((path.clone(), key.clone()));
        } else {
            static_assets.push((path.clone(), key.clone()));
        }
    }

    // Sort static assets by key for consistent output
    static_assets.sort_by(|a, b| a.1.cmp(&b.1));

    // Build template dependency map and sort templates
    let mut template_deps: HashMap<String, Option<String>> = HashMap::new();

    println!("cargo:warning=Analyzing template dependencies...");

    // First pass: read all template contents and find their dependencies
    for (path, key) in &template_files {
        println!("cargo:warning=Reading template: {key}");
        match fs::read_to_string(path) {
            Ok(content) => {
                // Look for {% extends "..." %} pattern
                if let Some(extends) = content
                    .lines()
                    .find(|line| line.trim().starts_with("{% extends"))
                {
                    if let Some(parent) = extends
                        .split('"')
                        .nth(1)
                        .or_else(|| extends.split('\'').nth(1))
                    {
                        template_deps.insert(key.clone(), Some(parent.to_string()));
                        println!("cargo:warning=Template {key} extends {parent}");
                    }
                } else {
                    template_deps.insert(key.clone(), None);
                    println!("cargo:warning=Template {key} has no parent");
                }
            }
            Err(e) => {
                println!("cargo:warning=Failed to read template {path}: {e}");
            }
        }
    }

    println!("cargo:warning=Template dependencies:");
    for (template, parent) in &template_deps {
        if let Some(p) = parent {
            println!("cargo:warning=  {template} -> {p}");
        } else {
            println!("cargo:warning=  {template} (no parent)");
        }
    }

    // Sort templates so that parents come before children
    let mut sorted_templates = Vec::new();
    let mut processed = HashSet::new();

    // First add all base templates (those with no parents), sorted alphabetically
    let mut base_templates: Vec<_> = template_deps
        .iter()
        .filter(|(_, parent)| parent.is_none())
        .map(|(key, _)| key.clone())
        .collect();
    base_templates.sort(); // Sort base templates alphabetically
    for key in base_templates {
        println!("cargo:warning=Adding base template: {key}");
        processed.insert(key.clone());
        sorted_templates.push(key);
    }

    // Then add all child templates, level by level
    let mut added_in_this_pass;
    while {
        added_in_this_pass = false;
        let mut level_templates = Vec::new();

        // Collect all templates at this level
        for (key, parent) in &template_deps {
            if processed.contains(key) {
                continue;
            }
            if let Some(parent) = parent {
                if processed.contains(parent) {
                    level_templates.push(key.clone());
                }
            }
        }

        // Sort templates at this level alphabetically
        level_templates.sort();

        // Add them to the final list
        for key in level_templates {
            if let Some(Some(parent)) = template_deps.get(&key) {
                println!("cargo:warning=Adding child template: {key} (extends {parent})");
            }
            processed.insert(key.clone());
            sorted_templates.push(key);
            added_in_this_pass = true;
        }

        added_in_this_pass
    } {}

    // Add any remaining templates that weren't processed, sorted alphabetically
    let mut remaining: Vec<_> = template_deps
        .keys()
        .filter(|key| !processed.contains(*key))
        .cloned()
        .collect();
    remaining.sort();
    for key in remaining {
        println!("cargo:warning=Adding unprocessed template: {key}");
        sorted_templates.push(key);
    }

    println!("cargo:warning=Final template order:");
    for (idx, template) in sorted_templates.iter().enumerate() {
        println!("cargo:warning=  {}. {}", idx + 1, template);
    }

    // Generate static assets file
    let static_file = output_path.join("static_assets.rs");

    // Create the static assets content
    let mut static_lines = vec![
        "#[must_use]\n".to_string(),
        "pub fn get_embedded_static_assets() -> std::collections::HashMap<String, &'static [u8]> {\n".to_string(),
        "    let mut assets = std::collections::HashMap::new();\n".to_string()
    ];

    for (path, key) in &static_assets {
        let insert_line = format!(
            r#"    assets.insert("{0}".to_string(), include_bytes!("{1}") as &[u8]);"#,
            key,
            path.replace('\\', "/")
        );
        static_lines.push(format!("{insert_line}\n"));
    }

    static_lines.push("    assets\n".to_string());
    static_lines.push("}\n".to_string());

    // Write static assets content to file
    let mut static_file = File::create(static_file)?;
    for line in static_lines {
        static_file.write_all(line.as_bytes())?;
    }

    // Generate templates file
    let templates_file = output_path.join("view_templates.rs");

    // Create the templates content with detailed comments
    let mut template_lines = vec![
        "/// Returns a BTreeMap of templates in dependency order (parents before children)\n"
            .to_string(),
        "#[must_use]\n".to_string(),
        "pub fn get_embedded_templates() -> std::collections::BTreeMap<String, &'static str> {\n"
            .to_string(),
        "    let mut templates = std::collections::BTreeMap::new();\n".to_string(),
    ];

    // Add templates in dependency order with comments
    for template_key in &sorted_templates {
        if let Some((path, _)) = template_files.iter().find(|(_, k)| k == template_key) {
            // Add a comment showing the dependency
            if let Some(Some(parent)) = template_deps.get(template_key) {
                template_lines.push(format!("    // Template that extends {parent}\n"));
            } else {
                template_lines.push("    // Base template with no parent\n".to_string());
            }

            let insert_line = format!(
                r#"    templates.insert("{0}".to_string(), include_str!("{1}"));"#,
                template_key,
                path.replace('\\', "/")
            );
            template_lines.push(format!("{insert_line}\n"));
        }
    }

    template_lines.push("\n    templates\n".to_string());
    template_lines.push("}\n".to_string());

    // Write templates content to file
    let mut templates_file = File::create(templates_file)?;
    for line in template_lines {
        templates_file.write_all(line.as_bytes())?;
    }

    println!(
        "cargo:warning=Generated code for {} static assets and {} templates",
        static_assets.len(),
        sorted_templates.len()
    );

    Ok(())
}

pub fn generate_empty_asset_files(output_path: &Path) -> io::Result<()> {
    // Generate empty static assets file
    let static_file = output_path.join("static_assets.rs");
    let static_code = r"#[must_use]
pub fn get_embedded_static_assets() -> std::collections::HashMap<String, &'static [u8]> {
    // No assets found
    std::collections::HashMap::new()
}
";
    let mut file = File::create(static_file)?;
    file.write_all(static_code.as_bytes())?;

    // Generate empty templates file
    let templates_file = output_path.join("view_templates.rs");
    let templates_code = r"#[must_use]
pub fn get_embedded_templates() -> std::collections::HashMap<String, &'static str> {
    // No templates found
    std::collections::HashMap::new()
}
";
    let mut file = File::create(templates_file)?;
    file.write_all(templates_code.as_bytes())?;

    Ok(())
}


================================================
FILE: build.rs
================================================
#[cfg(feature = "embedded_assets")]
use std::{env, path::Path};

fn main() {
    #[cfg(feature = "embedded_assets")]
    embedded_assets_main();

    #[cfg(not(feature = "embedded_assets"))]
    {
        // No-op when feature is disabled
    }
}

#[cfg(feature = "embedded_assets")]
fn embedded_assets_main() {
    // Import the embedded_assets module from the build directory
    #[path = "build/embedded_assets.rs"]
    mod embedded_assets;
    use embedded_assets::build_static_assets;

    // Get OUT_DIR environment variable - this is required for build scripts
    let out_dir = env::var("OUT_DIR").unwrap_or_else(|e| {
        // This should trigger a build failure
        panic!("OUT_DIR environment variable not set: {e}");
    });

    // Convert to a path
    let out_dir_path = Path::new(&out_dir);

    // Call the build_static_assets function with the OUT_DIR
    build_static_assets(out_dir_path);
}


================================================
FILE: docs-site/.gitignore
================================================
public/
node_modules/

================================================
FILE: docs-site/config.toml
================================================
# The URL the site will be built for
base_url = "https://loco.rs"
title = "Loco.rs - Productivity-first Rust Fullstack Web Framework"
description = "Loco.rs is like Ruby on Rails for Rust. Use it to quickly build and deploy Rust based apps from zero to production."


# Whether to automatically compile all Sass files in the sass directory
compile_sass = true

# Whether to generate a feed file for the site
generate_feeds = true

feed_filenames = ["blog/atom.xml", "blog/rss.xml"]

# When set to "true", the generated HTML files are minified.
minify_html = false

# The taxonomies to be rendered for the site and their configuration.
taxonomies = [
  { name = "authors" }, # Basic definition: no feed or pagination
]


# Whether to build a search index to be used later on by a JavaScript library
build_search_index = true

[markdown]
# Whether to do syntax highlighting
# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
highlight_theme = "css"
highlight_code = true
highlight_themes_css = [
  { theme = "OneHalfDark", filename = "syntax-theme-dark.css" },
  { theme = "OneHalfLight", filename = "syntax-theme-light.css" },
]
[extra]
# Put all your custom variables here

# Menu items
[[extra.menu.main]]
name = "Docs"
section = "docs"
url = "/docs/getting-started/tour/"
weight = 10

[[extra.menu.main]]
name = "Blog"
section = "blog"
url = "/blog/"
weight = 20

[[extra.menu.main]]
name = "Casts"
section = "casts"
url = "/casts/"

[[extra.menu.social]]
name = "Twitter"
pre = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-twitter"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg>'
url = "https://twitter.com/jondot"
weight = 10

[[extra.menu.social]]
name = "GitHub"
pre = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-github"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>'
url = "https://github.com/loco-rs/loco"
post = "v0.1.0"
weight = 20


[[extra.homepage.features]]
name = "Models"
description = 'Model your business with rich entities and avoid writing SQL, backed by SeaORM. Build relations, validation and custom logic on your entities for the best maintainability.'
example = '''```rust
impl Model {
  pub async fn find_by_email(db: &DatabaseConnection, email: &str)
  -> ModelResult<Self> {

      Users::find()
        .filter(eq(Column::Email, email))
        .one(db).await?
        .ok_or_else(|| ModelError::EntityNotFound)
  }
  
  pub async fn create_report(&self, ctx: &AppContext) -> Result<()> {
      ReportWorker::perform_later(
        &ctx, 
        ReportArgs{ user_id: self.id }
      ).await?;
  }
}
```
'''

[[extra.homepage.features]]
name = "Controllers"
description = 'Handle Web requests parameters, body, validation, and render a response that is content-aware. We use Axum for the best performance, simplicity and extensibility.'
example = '''```rust
pub async fn get_one(
    respond_to: RespondTo,
    Path(id): Path<i32>,
    State(ctx): State<AppContext>,
) -> Result<Response> {
    let item = Notes::find_by_id(id).one(&ctx.db).await?;
    match respond_to {
      RespondTo::Html => html_view(&item),
      _ => format::json(item),
    }
}

pub fn routes() -> Routes {
    Routes::new()
      .prefix("notes")
      .add("/{id}", get(get_one))
}
```
'''

[[extra.homepage.features]]
name = "Views"
description = 'Use server-rendered templates with Tera or JSON. Loco can render views on the server or work with a frontend app seamlessly. Configure your fullstack set up any way you like.'
example = '''```rust

// Literals
format::text("Loco")

// Tera view engine
format::render().view(v, "home/hello.html", json!({}))

// strongly typed JSON responsed, backed by `serde`
format::json(Health { ok: true })

// Etags, cookies, and more
format::render().etag("loco-etag")?.empty()

```
'''

[[extra.homepage.features]]
name = "Background Jobs"
description = 'Perform compute or I/O intensive jobs in the background with a Redis backed queue, or with threads. Implementing a worker is as simple as implementing a <code>perform</code> function for the <code>Worker</code> trait.'
example = '''```rust
impl worker::Worker<DownloadArgs> for UsersReportWorker {
    async fn perform(&self, args: DownloadArgs) -> worker::Result<()> {
        let all = Users::find()
          .all(&self.ctx.db)
          .await
          .map_err(Box::from)?;
        for user in &all {
          println!("user: {}", user.id);
        }
        Ok(())
    }
}

```
'''

[[extra.homepage.features]]
name = "Deployment"
description = 'Easily generate deployment configurations with a guided CLI interface. Select from deployment options for tailored deployment setups.'
example = '''```sh

$ cargo loco generate deployment
? ❯ Choose your deployment ›
❯ Docker
❯ Nginx

..
✔ ❯ Choose your deployment · Docker
skipped (exists): "Dockerfile"
added: ".dockerignore"

```
'''

[[extra.homepage.features]]
name = "Scheduler"
description = 'Simplifies the traditional, often cumbersome crontab system, making it easier and more elegant to schedule tasks or shell scripts.'
example = '''```yaml
jobs:
  db_vaccum:
    run: "db_vaccum.sh"
    shell: true
    schedule: "0 0 * * *"
    tags: ["maintenance"]

  send_birthday:
    run: "user_birthday_task"
    schedule: "Run every 2 hours"
    tags: ["marketing"]
       
```
'''


================================================
FILE: docs-site/content/_index.md
================================================
+++
title = "Loco"


# The homepage contents
[extra]
lead = 'The <em>one-person framework</em> for Rust for side-projects and startups'
url = "/docs/getting-started/tour/"
url_button = "Get started"

# Menu items
[[extra.menu.main]]
name = "Docs"
section = "docs"
url = "/docs/getting-started/tour/"
weight = 10

[[extra.menu.main]]
name = "Blog"
section = "blog"
url = "/blog/"
weight = 20

[[extra.menu.main]]
name = "Casts"
section = "casts"
url = "/casts/"

weight = 20
[[extra.list]]
title = "🔋 Batteries included"
content = 'Empower the 1-person team. Service, data, emails, background jobs, tasks, CLI to drive it, everything is included.'

[[extra.list]]
title = "🔮 Rails is great"
content = 'Loco follows Rails. There, I said it. Rails concepts are carefully adapted to modern Rust development.'

[[extra.list]]
title = "🏅 Deliver with confidence"
content = "Unapologetically optimized for the solo developer. Complexity and heavylifting is tucked away."

[[extra.list]]
title = "⚡️ Scale when needed"
content = "Split, reconfigure, or use only parts of Loco when you need to. Build and grow without pain."

[[extra.list]]
title = "🚀️ Build incrementally"
content = "Use what you need. Just a service, a service with a database, a background job worker, or a task."

[[extra.list]]
title = "🚦Test driven everything"
content = "Test your app with very little effort. Models, controllers, background jobs and more. Ship fast with confidence."

+++


================================================
FILE: docs-site/content/authors/_index.md
================================================
+++
title = "Authors"
description = "The authurs of the blog articles."
draft = false

# If add a new author page in this section, please add a new item,
# and the format is as follows:
#
# "author-name-in-url" = "the-full-path-of-the-author-page"
#
# Note: We use quoted keys here.
[extra.author_pages]
"team-loco" = "authors/team-loco.md"
"limpidcrypto" = "authors/limpidcrypto.md"
+++

The authors of the blog articles.

================================================
FILE: docs-site/content/authors/limpidcrypto.md
================================================
+++
title = "LimpidCrypto"
description = "Building open source tools for cryptocurrency development"
date = 2024-01-25T18:03:52+01:00
updated = 2024-01-25T18:03:52+01:00
draft = false
+++

Creating the Building Blocks for Cryptocurrency Development. To my [website](https://limpidcrypto.com).

================================================
FILE: docs-site/content/authors/team-loco.md
================================================
+++
title = "Team Loco"
description = "Creators of the Loco framework"
date = 2021-04-01T08:50:45+00:00
updated = 2021-04-01T08:50:45+00:00
draft = false
+++

Primary maintainers of the [Loco](https://loco.rs) framework: [Dotan Nahum](https://github.com/jondot), [Elad Kaplan](https://github.com/kaplanelad).



================================================
FILE: docs-site/content/blog/_index.md
================================================
+++
title = "Blog"
description = "Blog"
sort_by = "date"
paginate_by = 10
template = "blog/section.html"
+++


================================================
FILE: docs-site/content/blog/angular-frontend.md
================================================
+++
title = "Creating Frontend Website Using Angular"
description = "Setting up a Loco app for serving an Angular clientside app is easy. Learn how to configure and set up a full-stack Angular app with Loco."
date = 2024-01-25T18:03:52+01:00
updated = 2024-01-25T18:03:52+01:00
draft = false
template = "blog/page.html"

[taxonomies]
authors = ["LimpidCrypto"]

+++

## Overview

1. Create new SaaS project
2. Edit `.devcontainer/Dockerfile`
3. Reopen the project in the Dev Container
4. Delete frontend directory
5. Generate new Angular frontend
6. Build frontend
7. Edit `config/development.yml`
8. Start Loco

## Create new SaaS project

1. Run `loco new` to create a new project
2. Navigate through the instructions until you reach the point where to decide what type of project to create
3. Select "SaaS app (with DB and user auth)"

## Edit ".devcontainer/Dockerfile"

1. Open `.devcontainer/Dockerfile`
2. Replace the content with the following:

```Dockerfile
FROM mcr.microsoft.com/vscode/devcontainers/rust:0-1

# Install postgresql-client and sea-orm-cli
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
    && apt-get -y install --no-install-recommends postgresql-client \
    && cargo install sea-orm-cli \
    && chown -R vscode /usr/local/cargo

# Install Node.js and npm
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \
    && apt-get install -y nodejs
# Install Angular CLI
RUN npm install -g @angular/cli

COPY .env /.env
```

The Dockerfile will provide you with everything you need to develop a Loco app with an Angular frontend.

## Reopen the project in the Dev Container

With VSCode it is super easy to reopen and run the project in a Dev Container.

1. Press `Crtl + Shift + P`
2. Select `Dev Containers: Repopen in Container`
3. VSCode will open the project in the dev container. This can take a while when it is built for the first time.
4. Delete the existing `frontend` directory

Loco comes with a Vite React frontend. We can delete the whole directory because the Angular CLI will set up everything we need

## Generate new Angular frontend

1. From the project root execute `ng new frontend` to create a new Angular project
2. Navigate through the instructions

## Build frontend

1. Run `ng build` to build the Angular frontend

## Edit "config/development.yml"

As you may have noticed Angular has built the frontend into `frontend/dist/frontend/browser`. We now need to configure Loco to access the built frontend from there.

1. Open `config/development.yml`
2. Set the configs to the frontend build path:

   a. `server.middlewares.static.folder.path: "frontend/dist/frontend/browser"`

   b. `server.middlewares.static.fallback: "frontend/dist/frontend/browser/index.html"`

## Start Loco

1. Start Loco with `cargo loco start`
2. Open http://localhost:5150/

You should now see the Angular starter Website :smile:


================================================
FILE: docs-site/content/blog/axum-session.md
================================================
+++
title = "Building a Rust App with Axum Session"
description = "Add sessions to your app with Axum Sessions. Configure a session provider, and set up Axum Session and Loco with simple app hooks."
date = 2023-12-19T09:19:42+00:00
updated = 2023-12-19T09:19:42+00:00
draft = false
template = "blog/page.html"

[taxonomies]
authors = ["Team Loco"]

+++

To build a Rust app with [Axum session](https://crates.io/crates/axum_session), the first step is to choose your server. In this case, we'll use [loco](https://loco.rs) :)

Start by creating a new project and selecting the `SaaS app` template:

```sh
$ cargo install loco
$ loco new
✔ ❯ App name? · myapp
? ❯ What would you like to build? ›
  lightweight-service (minimal, only controllers and views)
  Rest API (with DB and user auth)
❯ SaaS app (with DB and user auth)
```

## Creating Session Memory Store Only

First, add the Axum session crate to Cargo.toml:

```toml
axum_session = {version = "0.10.1", default-features = false}
```

Then, add an Axum session layer to your router. Open app.rs and add the following hook:

```rust
pub struct App;
#[async_trait]
impl Hooks for App {
    fn app_name() -> &'static str {
        env!("CARGO_CRATE_NAME")
    }

    // Other hooks...
    async fn after_routes(router: AxumRouter, _ctx: &AppContext) -> Result<AxumRouter> {
        let session_config =
            axum_session::SessionConfig::default().with_table_name("sessions_table");

        let session_store =
            axum_session::SessionStore::<axum_session::SessionNullPool>::new(None, session_config)
                .await
                .unwrap();

        let router = router.layer(axum_session::SessionLayer::new(session_store));
        Ok(router)
    }
    // Other hooks...
}

```

Now, you can create your controller that uses Axum session. Use the `cargo loco generate controller` command:

```sh
❯ cargo loco generate controller mysession --api
    Finished dev [unoptimized + debuginfo] target(s) in 0.36s
     Running `target/debug/axum-session-cli generate controller mysession`
added: "src/controllers/mysession.rs"
injected: "src/controllers/mod.rs"
injected: "src/app.rs"
added: "tests/requests/mysession.rs"
injected: "tests/requests/mod.rs"
```

Open the `src/controllers/mysession.rs` file created by the controller generator and replace its content with the following code:

```rust
#![allow(clippy::unused_async)]
use axum_session::{Session, SessionNullPool};
use loco_rs::prelude::*;

pub async fn get_session(session: Session<SessionNullPool>) -> Result<()> {
    println!("{:#?}", session);
    format::empty()
}

pub fn routes() -> Routes {
    Routes::new().prefix("mysession").add("/", get(get_session))
}
```

Now, you can call the `http://127.0.0.1:5150/mysession` endpoint to see the session.

## Creating Session With DB Encryption

To add session DB encryption, include the Axum session crate and PostgreSQL with SQLx in Cargo.toml:

```toml
axum_session = {version = "0.10.1"}
sqlx = { version = "0.7.2", features = [
  "macros",
  "postgres",
  "_unstable-all-types",
  "tls-rustls",
  "runtime-tokio",
] }

```

Create a `session.rs` file with the following content:
The `connect_to_database` getting an `Database` configuration and returns a PgPool instance that axum session expected.

```rust
use sqlx::postgres::PgPool;
use loco_rs::{
    config::Database,
    errors::Error,
    Result,
};

async fn connect_to_database(config: &Database) -> Result<PgPool> {
    PgPool::connect(&config.uri)
        .await
        .map_err(|e| Error::Any(e.into()))
}

```

Add the Axum session layer to your router in `app.rs`:

```rust
use session; // This is the session.rs file
pub struct App;
#[async_trait]
impl Hooks for App {
    fn app_name() -> &'static str {
        env!("CARGO_CRATE_NAME")
    }

    // Other hooks...
    async fn after_routes(router: AxumRouter, ctx: &AppContext) -> Result<AxumRouter> {
        let conn = session.connect_to_database(&ctx.config.database).await?;
        let session_config = axum_session::SessionConfig::default()
            .with_table_name("sessions_table")
            .with_key(axum_session::Key::generate())
            .with_database_key(axum_session::Key::generate())
            .with_security_mode(axum_session::SecurityMode::PerSession);

        let session_store = axum_session::SessionStore::<axum_session::SessionPgPool>::new(
            Some(conn.clone().into()),
            session_config,
        )
        .await
        .unwrap();

        let router = router.layer(axum_session::SessionLayer::new(session_store));
        Ok(router)
    }
    // Other hooks...
}

```

Create the controller as before using `cargo loco generate controller`

```sh
❯ cargo loco generate controller mysession --api
    Finished dev [unoptimized + debuginfo] target(s) in 0.36s
     Running `target/debug/axum-session-cli generate controller mysession`
added: "src/controllers/mysession.rs"
injected: "src/controllers/mod.rs"
injected: "src/app.rs"
added: "tests/requests/mysession.rs"
injected: "tests/requests/mod.rs"
```

and replace the content of `src/controllers/mysession.rs` with the provided code.

```rust
#![allow(clippy::unused_async)]
use axum_session::{Session, SessionPgPool};
use loco_rs::prelude::*;

pub async fn get_session(session: Session<SessionPgPool>) -> Result<()> {
    println!("{:#?}", session);
    format::empty()
}

pub fn routes() -> Routes {
    Routes::new().prefix("mysession").add("/", get(get_session))
}

```

Now, calling the `http://127.0.0.1:5150/mysession` endpoint will display the session.


================================================
FILE: docs-site/content/blog/deploy-aws.md
================================================
+++
title = "Deploying Rust App with Terraform on AWS Fargate"
description = "Learn how to deploy a Loco app with Terraform (IaC). Generate a deployment with Loco generators and set it up step-by-step."
date = 2023-12-20T16:04:40+00:00
updated = 2023-12-16T04:20:40+00:00
draft = false
template = "blog/page.html"

[taxonomies]
authors = ["Antonio Souza"]

+++

In today's rapidly evolving technological landscape, Infrastructure as Code (IaC) has become a cornerstone for efficient, scalable, and maintainable cloud infrastructure deployment. IaC involves managing and provisioning computing infrastructure through machine-readable script files, rather than through physical hardware configuration or interactive configuration tools. This allows for the automation of infrastructure deployment and management, which in turn reduces the risk of human error and increases the speed of deployment.

In this article, we will explore how to deploy a Rust app built with [loco](https://loco.rs) on AWS Fargate using Terraform. We will start by creating a new project and selecting the `Rest API` template:

````sh

```sh
$ cargo install loco
$ loco new
✔ ❯ App name? · myapp
? ❯ What would you like to build? ›
  lightweight-service (minimal, only controllers and views)
❯ Rest API (with DB and user auth)
  SaaS app (with DB and user auth)
````

## Prerequisites

To deploy our app on AWS Fargate, we will need to have the following tools installed:

- [Docker](https://docs.docker.com/get-docker/) - Docker is a containerization platform that allows you to package your application and all of its dependencies into a standardized unit for software development.
- [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli) - Terraform is an open-source infrastructure as code software tool that enables you to safely and predictably create, change, and improve infrastructure.
- [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) - The AWS Command Line Interface (CLI) is a unified tool to manage your AWS services.

## Creating the Docker Image

To create the Docker image for our app, we will use the loco CLI. The `cargo loco generate deployment` command will create a Docker image for our app. It will also create a `Dockerfile` for us, which we can use to build the image.

```sh
$ cargo loco generate deployment
? ❯ Choose your deployment ›
❯ Docker

added: "Dockerfile"
added: ".dockerignore"
```

Now, we can build the Docker image which will be used to deploy our app on AWS Fargate.

```sh
$ docker build -t myapp .

[+] Building 237.1s (16/16) FINISHED                                                                                                               docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                                                                               0.0s
 => => transferring Dockerfile: 331B                                                                                                                               0.0s
 ...
 => => writing image sha256:07416ca8195e4026ab65bc567f990ea83141aa10890f8443deb8f54a8bae7f0a                                                                       0.0s
 => => naming to docker.io/library/myapp
```

## Setting up AWS

To deploy our app on AWS Fargate, we will need to create an AWS account and set up the AWS CLI. You can create an AWS account [here](https://portal.aws.amazon.com/billing/signup#/start/email).

You will also need to install the AWS CLI. You can find instructions on how to do this [here](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html).

Finally, you need to create an IAM user to use with the AWS CLI. You can find instructions on how to do this [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html).

Now, we can configure the AWS CLI with the credentials of the IAM user we just created.

```sh
$ aws configure
AWS Access Key ID [None]: <your access key id>
AWS Secret Access Key [None]: <your secret access key>
Default region name [None]: <your region>
Default output format [None]: json
```

## Creating the repository on ECR

To deploy our app on AWS Fargate, we will need to create a repository on ECR. You can do this by running the following command:

```sh
$ aws ecr create-repository --repository-name myapp

{
    "repository": {
        "repositoryArn": "arn:aws:ecr:us-east-1:123456789012:repository/myapp",
        "registryId": "123456789012",
        "repositoryName": "myapp",
        "repositoryUri": "123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp",
        "createdAt": 1627981234.0,
        "imageTagMutability": "MUTABLE",
        "imageScanningConfiguration": {
            "scanOnPush": false
        }
    }
}
```

## Pushing the Docker image to ECR

Now, we can push the Docker image to ECR. You can do this by running the following commands:

-1. Log in to ECR

```sh
$ aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
```

-2. Tag the Docker image

```sh
$ docker tag myapp:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:latest
```

-3. Push the Docker image to ECR

```sh
$ docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:latest
```

## Creating the main.tf file for Terraform

This is the main Terraform file that will be used to deploy our app on AWS Fargate. It will create the following resources:

```hcl
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "~> 4.0"
    }
    archive = {
      source = "hashicorp/archive"
      version = "~> 2.2.0"
    }
  }

  required_version = "~> 1.0"
}

# Configure the AWS Provider
provider "aws" {
  region = "us-east-1" // Change this to your region
  access_key = "<your access key>" // Change this to your access key
  secret_key = "your secret key" // Change this to your secret key
}

resource "aws_ecr_repository" "myapp" {
  name = "myapp"
}

resource "aws_ecs_cluster" "myapp_cluster" {
  name = "myapp_cluster"
}

resource "aws_cloudwatch_log_group" "myapp" {
  name = "/ecs/myapp"
}

resource "aws_ecs_task_definition" "myapp_task" {
  family                   = "myapp-task"
  container_definitions    = <<DEFINITION
  [
    {
      "name": "myapp-task",
      "image": "${aws_ecr_repository.myapp.repository_url}",
      "essential": true,
      "portMappings": [
        {
          "containerPort": 5150
        }
      ],
      "command": ["start"],
      "memory": 512,
      "cpu": 256,
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-region": "us-east-2",
          "awslogs-group": "/ecs/myapp",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ]
  DEFINITION
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  memory                   = 512
  cpu                      = 256
  execution_role_arn       = aws_iam_role.ecsTaskExecutionRole.arn
}

resource "aws_iam_role" "ecsTaskExecutionRole" {
  name               = "ecsTaskExecutionRoleMyapp"
  assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json
}

data "aws_iam_policy_document" "assume_role_policy" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ecs-tasks.amazonaws.com"]
    }
  }
}

resource "aws_iam_role_policy_attachment" "ecsTaskExecutionRole_policy" {
  role       = aws_iam_role.ecsTaskExecutionRole.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

resource "aws_alb" "myapp" {
  name               = "myapp-lb"
  internal           = false
  load_balancer_type = "application"
  enable_deletion_protection = true

  subnets = [
    aws_subnet.public_d.id,
    aws_subnet.public_e.id,
  ]

  security_groups = [
    aws_security_group.http.id,
    aws_security_group.https.id,
    aws_security_group.egress_all.id,
  ]

  depends_on = [aws_internet_gateway.igw]
}


resource "aws_security_group" "load_balancer_security_group" {
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
resource "aws_lb_target_group" "myapp" {
  name        = "myapp-tg"
  port        = 5150
  protocol    = "HTTP"
  target_type = "ip"
  vpc_id      = aws_vpc.myapp_vpc.id

  health_check {
    enabled = true
    path    = "/_health"
    matcher = "200,202"
  }

  depends_on = [aws_alb.myapp]
}

resource "aws_alb_listener" "myapp_http" {
  load_balancer_arn = aws_alb.myapp.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type =  "redirect"
    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}

resource "aws_alb_listener" "myapp_https" {
  load_balancer_arn = aws_alb.myapp.arn
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-2016-08"

  certificate_arn = "<your arn for the certificate>" // Change this to your certificate ARN

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.myapp.arn
  }
}

output "alb_url" {
  value = "https://${aws_alb.myapp.dns_name}"
}
resource "aws_ecs_service" "myapp" {
  name            = "myapp-service"
  cluster         = aws_ecs_cluster.myapp_cluster.id
  task_definition = aws_ecs_task_definition.myapp_task.arn
  launch_type     = "FARGATE"
  desired_count   = 1

  load_balancer {
    target_group_arn = aws_lb_target_group.myapp.arn
    container_name   = aws_ecs_task_definition.myapp_task.family
    container_port   = 5150
  }

  network_configuration {
    assign_public_ip = false

    security_groups = [
      aws_security_group.egress_all.id,
      aws_security_group.ingress_api.id,
    ]

    subnets = [
    aws_subnet.private_d.id,
    aws_subnet.private_e.id,
    ]
  }
}


resource "aws_security_group" "service_security_group" {
  ingress {
    from_port       = 0
    to_port         = 0
    protocol        = "-1"
    security_groups = ["${aws_security_group.load_balancer_security_group.id}"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
```

This file will create the following resources:

- An ECR repository for our app
- An ECS cluster for our app
- An ECS task definition for our app
- An ECS service for our app

Now, we need to create a `network.tf` file to define the network configuration for our app. This file will create the following resources:

```hcl
resource "aws_vpc" "myapp_vpc" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "public_d" {
  vpc_id            = aws_vpc.myapp_vpc.id
  cidr_block        = "10.0.1.0/25"
  availability_zone = "us-east-2a"

  tags = {
    "Name" = "public | us-east-2a"
  }
}

resource "aws_subnet" "private_d" {
  vpc_id            = aws_vpc.myapp_vpc.id
  cidr_block        = "10.0.2.0/25"
  availability_zone = "us-east-2b"

  tags = {
    "Name" = "private | us-east-2b"
  }
}

resource "aws_subnet" "public_e" {
  vpc_id            = aws_vpc.myapp_vpc.id
  cidr_block        = "10.0.1.128/25"
  availability_zone = "us-east-2c"

  tags = {
    "Name" = "public | us-east-2c"
  }
}

resource "aws_subnet" "private_e" {
  vpc_id            = aws_vpc.myapp_vpc.id
  cidr_block        = "10.0.2.128/25"
  availability_zone = "us-east-2c"

  tags = {
    "Name" = "private | us-east-2c"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.myapp_vpc.id
  tags = {
    "Name" = "public"
  }
}

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.myapp_vpc.id
  tags = {
    "Name" = "private"
  }
}

resource "aws_route_table_association" "public_d_subnet" {
  subnet_id      = aws_subnet.public_d.id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "private_d_subnet" {
  subnet_id      = aws_subnet.private_d.id
  route_table_id = aws_route_table.private.id
}

resource "aws_route_table_association" "public_e_subnet" {
  subnet_id      = aws_subnet.public_e.id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "private_e_subnet" {
  subnet_id      = aws_subnet.private_e.id
  route_table_id = aws_route_table.private.id
}

resource "aws_eip" "nat" {
  vpc = true
}

resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.myapp_vpc.id
}

resource "aws_nat_gateway" "ngw" {
  subnet_id     = aws_subnet.public_d.id
  allocation_id = aws_eip.nat.id

  depends_on = [aws_internet_gateway.igw]
}

resource "aws_route" "public_igw" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.igw.id
}

resource "aws_route" "private_ngw" {
  route_table_id         = aws_route_table.private.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.ngw.id
}

resource "aws_security_group" "http" {
  name        = "http"
  description = "HTTP traffic"
  vpc_id      = aws_vpc.myapp_vpc.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "TCP"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "https" {
  name        = "https"
  description = "HTTPS traffic"
  vpc_id      = aws_vpc.myapp_vpc.id

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "TCP"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "egress_all" {
  name        = "egress-all"
  description = "Allow outbound traffic"
  vpc_id      = aws_vpc.myapp_vpc.id

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "ingress_api" {
  name        = "ingress-api"
  description = "Allow ingress to App"
  vpc_id      = aws_vpc.myapp_vpc.id

  ingress {
    from_port   = 5150
    to_port     = 5150
    protocol    = "TCP"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
```

The network configuration will be responsible for creating all the infrastructure needed to deploy our app on AWS Fargate in terms of networking. I recommend you to read the [AWS Fargate documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html) to understand how it works, also you can read the Terraform documentation for [AWS Fargate](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_task_definition) and [AWS VPC](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc).

So, now we have the main Terraform file and the network configuration file for our app. We can now deploy our app on AWS Fargate.

## Deploying the app on AWS Fargate

To deploy our app on AWS Fargate, we will need to run the following commands:

-1. Initialize Terraform

```sh
$ terraform init
```

-2. Plan the deployment

```sh
$ terraform plan
```

-3. Apply the deployment

````sh
$ terraform apply
```****

Theses commands will create all the resources we need to deploy our app on AWS Fargate. After running you will see the url from our alb_url output.

```sh
Apply complete! Resources: 20 added, 0 changed, 0 destroyed.

Outputs:

alb_url = https://myapp-lb-1234567890.us-east-2.elb.amazonaws.com
````

Now, we can access our app by going to the url from our alb_url output.

## Conclusion

In this article, we explored how to deploy a Rust app built with loco on AWS Fargate using Terraform. We started by creating a new project and selecting the `Rest API` template. Then, we created the Docker image for our app and pushed it to ECR. Finally, we created the main Terraform file and the network configuration file for our app and deployed it on AWS Fargate.

This approach allows us to deploy our app on AWS Fargate in a fast and reliable way. It also allows us to easily scale our app by adding more instances of it.


================================================
FILE: docs-site/content/blog/frontend-website.md
================================================
+++
title = "Creating Frontend Website"
description = "Build a REST API quickly with Loco and then follow by build
Download .txt
gitextract_8x970ict/

├── .cargo/
│   └── config.toml
├── .clippy.toml
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   ├── config.yml
│   │   ├── feature-request.md
│   │   └── suggestion.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── docs.yml
│       ├── loco-gen-ci.yml
│       ├── loco-gen-deploy.yml
│       ├── loco-new.yml
│       ├── loco-rs-ci-sanity.yml
│       └── loco-rs-ci.yml
├── .gitignore
├── .rustfmt.toml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Cargo.toml
├── DEVELOPMENT.md
├── LICENSE
├── README-pt_BR.md
├── README-zh_CN.md
├── README.es.md
├── README.fr.md
├── README.ja.md
├── README.ko.md
├── README.md
├── README.ru.md
├── SECURITY.md
├── build/
│   └── embedded_assets.rs
├── build.rs
├── docs-site/
│   ├── .gitignore
│   ├── config.toml
│   ├── content/
│   │   ├── _index.md
│   │   ├── authors/
│   │   │   ├── _index.md
│   │   │   ├── limpidcrypto.md
│   │   │   └── team-loco.md
│   │   ├── blog/
│   │   │   ├── _index.md
│   │   │   ├── angular-frontend.md
│   │   │   ├── axum-session.md
│   │   │   ├── deploy-aws.md
│   │   │   ├── frontend-website.md
│   │   │   └── hello-world.md
│   │   ├── casts/
│   │   │   ├── 001-dynamic-responses-and-content-types.md
│   │   │   ├── 002-routes-and-prefixes.md
│   │   │   ├── 003-scaffolding-crud-with-html.md
│   │   │   ├── 004-creating-tasks.md
│   │   │   ├── 005-testing-tasks.md
│   │   │   ├── 006-mailers.md
│   │   │   ├── 007-htmx.md
│   │   │   └── _index.md
│   │   ├── docs/
│   │   │   ├── _index.md
│   │   │   ├── extras/
│   │   │   │   ├── _index.md
│   │   │   │   ├── authentication.md
│   │   │   │   ├── pluggability.md
│   │   │   │   ├── upgrades.md
│   │   │   │   └── websocket.md
│   │   │   ├── getting-started/
│   │   │   │   ├── _index.md
│   │   │   │   ├── axum-users.md
│   │   │   │   ├── guide.md
│   │   │   │   ├── starters.md
│   │   │   │   └── tour/
│   │   │   │       └── index.md
│   │   │   ├── infrastructure/
│   │   │   │   ├── _index.md
│   │   │   │   ├── cache.md
│   │   │   │   ├── data.md
│   │   │   │   ├── deployment.md
│   │   │   │   └── storage.md
│   │   │   ├── processing/
│   │   │   │   ├── _index.md
│   │   │   │   ├── mailers.md
│   │   │   │   ├── scheduler.md
│   │   │   │   ├── task.md
│   │   │   │   └── workers.md
│   │   │   ├── resources/
│   │   │   │   ├── _index.md
│   │   │   │   ├── around-the-web.md
│   │   │   │   └── faq.md
│   │   │   └── the-app/
│   │   │       ├── _index.md
│   │   │       ├── controller.md
│   │   │       ├── models.md
│   │   │       ├── views.md
│   │   │       └── your-project.md
│   │   └── privacy-policy/
│   │       └── _index.md
│   ├── package.json
│   ├── static/
│   │   ├── ahrefs_f06cfb9c2671c1b7a5b6eec0d47a07719bd6d5a2240b829cad6a3f40684fa370
│   │   ├── js/
│   │   │   ├── main.js
│   │   │   └── search.js
│   │   ├── styles/
│   │   │   └── styles.css
│   │   ├── syntax-theme-dark.css
│   │   └── syntax-theme-light.css
│   ├── styles/
│   │   └── styles.css
│   ├── tailwind.config.js
│   ├── templates/
│   │   ├── 404.html
│   │   ├── base.html
│   │   ├── blog/
│   │   │   ├── atom.xml
│   │   │   ├── page.html
│   │   │   ├── rss.xml
│   │   │   └── section.html
│   │   ├── casts/
│   │   │   ├── page.html
│   │   │   └── section.html
│   │   ├── docs/
│   │   │   ├── page.html
│   │   │   └── section.html
│   │   ├── index.html
│   │   ├── macros/
│   │   │   ├── docs-edit-page.html
│   │   │   ├── docs-navigation.html
│   │   │   ├── docs-sidebar.html
│   │   │   ├── docs-toc.html
│   │   │   ├── footer.html
│   │   │   ├── header.html
│   │   │   ├── javascript.html
│   │   │   ├── page-publish-metadata.html
│   │   │   └── youtube.html
│   │   ├── page.html
│   │   ├── section.html
│   │   ├── shortcodes/
│   │   │   └── get_env.html
│   │   ├── taxonomy_list.html
│   │   └── taxonomy_single.html
│   └── translations/
│       └── tour-fr.md
├── loco-cli/
│   ├── .gitignore
│   ├── .rustfmt.toml
│   ├── Cargo.toml
│   ├── README.md
│   └── src/
│       ├── bin/
│       │   └── main.rs
│       └── lib.rs
├── loco-gen/
│   ├── .gitattributes
│   ├── Cargo.toml
│   ├── src/
│   │   ├── controller.rs
│   │   ├── infer.rs
│   │   ├── lib.rs
│   │   ├── mappings.json
│   │   ├── migration.rs
│   │   ├── model.rs
│   │   ├── scaffold.rs
│   │   ├── snapshots/
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_big_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_bool].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_double].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_float].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array!_string].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_big_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_bool].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_double].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_float].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array^_string].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_big_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_bool].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_double].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_float].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_array_string].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_int!_big_int!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_int^_big_int^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_int_big_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_unsigned!_big_unsigned!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_unsigned^_big_unsigned^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_big_unsigned_big_unsigned].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_binary_len!_binary_len!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_binary_len^_binary_len^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_binary_len_binary_len].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_blob!_blob!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_blob^_blob^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_blob_blob].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_bool!_bool!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_bool_bool].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date!_date!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date^_date^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date_date].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date_time!_date_time!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date_time^_date_time^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_date_time_date_time].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal!_decimal!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal^_decimal^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_decimal].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_len!_decimal_len!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_len^_decimal_len^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_len_decimal_len].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_double!_double!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_double^_double^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_double_double].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_float!_float!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_float^_float^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_float_float].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_int!_int!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_int^_int^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_int_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_json!_json!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_json_json].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_jsonb!_jsonb!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_jsonb^_jsonb^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_jsonb_jsonb].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_money!_money!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_money^_money^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_money_money].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_int!_small_int!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_int^_small_int^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_int_small_int].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_unsigned!_small_unsigned!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_unsigned^_small_unsigned^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_small_unsigned_small_unsigned].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_string!_string!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_string^_string^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_string_string].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_text!_text!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_text^_text^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_text_text].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_tstz!_tstz!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_tstz_tstz].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_unsigned!_unsigned!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_unsigned^_unsigned^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_unsigned_unsigned].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_uuid!_uuid!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_uuid^_uuid^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_uuid_uuid].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_var_binary!_var_binary!].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_var_binary^_var_binary^].snap
│   │   │   ├── loco_gen__tera_ext__tests__can_render_form_field_[form_var_binary_var_binary].snap
│   │   │   └── loco_gen__tera_ext__tests__can_render_view_field.snap
│   │   ├── template.rs
│   │   ├── templates/
│   │   │   ├── controller/
│   │   │   │   ├── api/
│   │   │   │   │   ├── controller.t
│   │   │   │   │   └── test.t
│   │   │   │   ├── html/
│   │   │   │   │   ├── controller.t
│   │   │   │   │   └── view.t
│   │   │   │   └── htmx/
│   │   │   │       ├── controller.t
│   │   │   │       └── view.t
│   │   │   ├── data/
│   │   │   │   ├── 0_mod.t
│   │   │   │   ├── data.t
│   │   │   │   ├── mod.t
│   │   │   │   └── struct.t
│   │   │   ├── deployment/
│   │   │   │   ├── docker/
│   │   │   │   │   ├── docker.t
│   │   │   │   │   └── ignore.t
│   │   │   │   └── nginx/
│   │   │   │       └── nginx.t
│   │   │   ├── mailer/
│   │   │   │   ├── html.t
│   │   │   │   ├── mailer.t
│   │   │   │   ├── subject.t
│   │   │   │   └── text.t
│   │   │   ├── migration/
│   │   │   │   ├── add_columns.t
│   │   │   │   ├── add_references.t
│   │   │   │   ├── empty.t
│   │   │   │   ├── join_table.t
│   │   │   │   └── remove_columns.t
│   │   │   ├── model/
│   │   │   │   ├── model.t
│   │   │   │   └── test.t
│   │   │   ├── scaffold/
│   │   │   │   ├── api/
│   │   │   │   │   ├── controller.t
│   │   │   │   │   └── test.t
│   │   │   │   ├── html/
│   │   │   │   │   ├── base.t
│   │   │   │   │   ├── controller.t
│   │   │   │   │   ├── view.t
│   │   │   │   │   ├── view_create.t
│   │   │   │   │   ├── view_edit.t
│   │   │   │   │   ├── view_list.t
│   │   │   │   │   └── view_show.t
│   │   │   │   └── htmx/
│   │   │   │       ├── base.t
│   │   │   │       ├── controller.t
│   │   │   │       ├── view.t
│   │   │   │       ├── view_create.t
│   │   │   │       ├── view_edit.t
│   │   │   │       ├── view_list.t
│   │   │   │       └── view_show.t
│   │   │   ├── scheduler/
│   │   │   │   └── scheduler.t
│   │   │   ├── task/
│   │   │   │   ├── task.t
│   │   │   │   └── test.t
│   │   │   └── worker/
│   │   │       ├── test.t
│   │   │       └── worker.t
│   │   ├── tera_ext.rs
│   │   └── testutil.rs
│   └── tests/
│       ├── db.rs
│       ├── mod.rs
│       ├── snapshots/
│       │   ├── db__migrations_flow_postgres.snap
│       │   ├── db__migrations_flow_sqlite.snap
│       │   ├── r#mod__db__migrations_flow_postgres.snap
│       │   └── r#mod__db__migrations_flow_sqlite.snap
│       └── templates/
│           ├── controller.rs
│           ├── deployment.rs
│           ├── mailer.rs
│           ├── migration.rs
│           ├── mod.rs
│           ├── model.rs
│           ├── scaffold.rs
│           ├── scheduler.rs
│           ├── snapshots/
│           │   ├── generate[controller_file]@Api_controller.snap
│           │   ├── generate[controller_file]@Api_scaffold.snap
│           │   ├── generate[controller_file]@Html_controller.snap
│           │   ├── generate[controller_file]@Html_scaffold.snap
│           │   ├── generate[controller_file]@Htmx_controller.snap
│           │   ├── generate[controller_file]@Htmx_scaffold.snap
│           │   ├── generate[controller_file]@scheduler.snap
│           │   ├── generate[controller_file]@task.snap
│           │   ├── generate[controller_file]@worker.snap
│           │   ├── generate[docker_file_[0]_[false]]@deployment.snap
│           │   ├── generate[docker_file_[0]_[true]]@deployment.snap
│           │   ├── generate[docker_file_[2]_[false]]@deployment.snap
│           │   ├── generate[docker_file_[2]_[true]]@deployment.snap
│           │   ├── generate[html_t_file]@mailer.snap
│           │   ├── generate[mailer_mod_rs]@mailer.snap
│           │   ├── generate[migration_file]@Api_scaffold.snap
│           │   ├── generate[migration_file]@Html_scaffold.snap
│           │   ├── generate[migration_file]@Htmx_scaffold.snap
│           │   ├── generate[migration_file]@add_column_migration.snap
│           │   ├── generate[migration_file]@add_reference_migration.snap
│           │   ├── generate[migration_file]@create_join_table_migration.snap
│           │   ├── generate[migration_file]@create_join_table_without_tz_migration.snap
│           │   ├── generate[migration_file]@create_table_migration.snap
│           │   ├── generate[migration_file]@create_table_without_tz_migration.snap
│           │   ├── generate[migration_file]@empty_migration.snap
│           │   ├── generate[migration_file]@model.snap
│           │   ├── generate[migration_file]@remove_columns_migration.snap
│           │   ├── generate[nginx]@deployment.snap
│           │   ├── generate[subject_t_file]@mailer.snap
│           │   ├── generate[test_model]@Api_scaffold.snap
│           │   ├── generate[test_model]@Html_scaffold.snap
│           │   ├── generate[test_model]@Htmx_scaffold.snap
│           │   ├── generate[test_model]@model.snap
│           │   ├── generate[tests_controller_mod_rs]@Api_controller.snap
│           │   ├── generate[tests_task_file]@task.snap
│           │   ├── generate[tests_worker_file]@worker.snap
│           │   ├── generate[text_t_file]@mailer.snap
│           │   ├── generate[views_[create]]@Html_scaffold.snap
│           │   ├── generate[views_[create]]@Htmx_scaffold.snap
│           │   ├── generate[views_[edit]]@Html_scaffold.snap
│           │   ├── generate[views_[edit]]@Htmx_scaffold.snap
│           │   ├── generate[views_[list]]@Html_scaffold.snap
│           │   ├── generate[views_[list]]@Htmx_scaffold.snap
│           │   ├── generate[views_[show]]@Html_scaffold.snap
│           │   ├── generate[views_[show]]@Htmx_scaffold.snap
│           │   ├── generate[views_rs]@Html_scaffold.snap
│           │   ├── generate[views_rs]@Htmx_scaffold.snap
│           │   ├── generate_result@add_column_migration.snap
│           │   ├── generate_result@add_reference_migration.snap
│           │   ├── generate_result@create_join_table_migration.snap
│           │   ├── generate_result@create_join_table_without_tz_migration.snap
│           │   ├── generate_result@create_table_migration.snap
│           │   ├── generate_result@create_table_without_tz_migration.snap
│           │   ├── generate_result@empty_migration.snap
│           │   ├── generate_result@remove_columns_migration.snap
│           │   ├── generate_results@Api_controller.snap
│           │   ├── generate_results@Api_scaffold.snap
│           │   ├── generate_results@Html_controller.snap
│           │   ├── generate_results@Html_scaffold.snap
│           │   ├── generate_results@Htmx_controller.snap
│           │   ├── generate_results@Htmx_scaffold.snap
│           │   ├── inject[.config_toml]@deployment.snap
│           │   ├── inject[app_rs]@Api_controller.snap
│           │   ├── inject[app_rs]@Api_scaffold.snap
│           │   ├── inject[app_rs]@Html_controller.snap
│           │   ├── inject[app_rs]@Html_scaffold.snap
│           │   ├── inject[app_rs]@Htmx_controller.snap
│           │   ├── inject[app_rs]@Htmx_scaffold.snap
│           │   ├── inject[app_rs]@task.snap
│           │   ├── inject[app_rs]@worker.snap
│           │   ├── inject[controller_mod_rs]@Api_controller.snap
│           │   ├── inject[controller_mod_rs]@Api_scaffold.snap
│           │   ├── inject[controller_mod_rs]@Html_controller.snap
│           │   ├── inject[controller_mod_rs]@Html_scaffold.snap
│           │   ├── inject[controller_mod_rs]@Htmx_controller.snap
│           │   ├── inject[controller_mod_rs]@Htmx_scaffold.snap
│           │   ├── inject[mailer_mod_rs]@mailer.snap
│           │   ├── inject[migration_lib]@Api_scaffold.snap
│           │   ├── inject[migration_lib]@Html_scaffold.snap
│           │   ├── inject[migration_lib]@Htmx_scaffold.snap
│           │   ├── inject[migration_lib]@add_column_migration.snap
│           │   ├── inject[migration_lib]@add_reference_migration.snap
│           │   ├── inject[migration_lib]@create_join_table_migration.snap
│           │   ├── inject[migration_lib]@create_join_table_without_tz_migration.snap
│           │   ├── inject[migration_lib]@create_table_migration.snap
│           │   ├── inject[migration_lib]@create_table_without_tz_migration.snap
│           │   ├── inject[migration_lib]@empty_migration.snap
│           │   ├── inject[migration_lib]@model.snap
│           │   ├── inject[migration_lib]@remove_columns_migration.snap
│           │   ├── inject[task_mod_rs]@task.snap
│           │   ├── inject[test_mod]@Api_scaffold.snap
│           │   ├── inject[test_mod]@Html_scaffold.snap
│           │   ├── inject[test_mod]@Htmx_scaffold.snap
│           │   ├── inject[test_mod]@model.snap
│           │   ├── inject[tests_controller_mod_rs]@Api_controller.snap
│           │   ├── inject[tests_task_mod]@task.snap
│           │   ├── inject[tests_worker_mod]@worker.snap
│           │   ├── inject[views_[GET]]@Html_controller.snap
│           │   ├── inject[views_[GET]]@Htmx_controller.snap
│           │   ├── inject[views_[POST]]@Html_controller.snap
│           │   ├── inject[views_[POST]]@Htmx_controller.snap
│           │   ├── inject[views_mod_rs]@Html_scaffold.snap
│           │   ├── inject[views_mod_rs]@Htmx_scaffold.snap
│           │   └── inject[worker_mod_rs]@worker.snap
│           ├── task.rs
│           ├── utils.rs
│           └── worker.rs
├── loco-new/
│   ├── .gitignore
│   ├── Cargo.lock
│   ├── Cargo.toml
│   ├── README.md
│   ├── base_template/
│   │   ├── .cargo/
│   │   │   └── config.toml.t
│   │   ├── .github/
│   │   │   └── workflows/
│   │   │       └── ci.yaml.t
│   │   ├── .gitignore
│   │   ├── .rustfmt.toml
│   │   ├── Cargo.toml.t
│   │   ├── README.md
│   │   ├── assets/
│   │   │   ├── i18n/
│   │   │   │   ├── de-DE/
│   │   │   │   │   └── main.ftl
│   │   │   │   ├── en-US/
│   │   │   │   │   └── main.ftl
│   │   │   │   └── shared.ftl
│   │   │   ├── static/
│   │   │   │   └── 404.html
│   │   │   └── views/
│   │   │       └── home/
│   │   │           └── hello.html
│   │   ├── config/
│   │   │   ├── development.yaml.t
│   │   │   └── test.yaml.t
│   │   ├── examples/
│   │   │   └── playground.rs.t
│   │   ├── frontend/
│   │   │   ├── .gitignore
│   │   │   ├── README.md
│   │   │   ├── biome.json
│   │   │   ├── package.json
│   │   │   ├── rsbuild.config.ts
│   │   │   ├── src/
│   │   │   │   ├── LocoSplash.tsx
│   │   │   │   ├── env.d.ts
│   │   │   │   ├── index.css
│   │   │   │   └── index.tsx
│   │   │   └── tsconfig.json
│   │   ├── migration/
│   │   │   ├── Cargo.toml.t
│   │   │   └── src/
│   │   │       ├── lib.rs.t
│   │   │       └── m20220101_000001_users.rs
│   │   ├── src/
│   │   │   ├── app.rs.t
│   │   │   ├── bin/
│   │   │   │   ├── main.rs.t
│   │   │   │   └── tool.rs.t
│   │   │   ├── controllers/
│   │   │   │   ├── auth.rs
│   │   │   │   ├── home.rs
│   │   │   │   └── mod.rs.t
│   │   │   ├── data/
│   │   │   │   └── mod.rs.t
│   │   │   ├── fixtures/
│   │   │   │   └── users.yaml
│   │   │   ├── initializers/
│   │   │   │   ├── mod.rs.t
│   │   │   │   └── view_engine.rs
│   │   │   ├── lib.rs.t
│   │   │   ├── mailers/
│   │   │   │   ├── auth/
│   │   │   │   │   ├── forgot/
│   │   │   │   │   │   ├── html.t
│   │   │   │   │   │   ├── subject.t
│   │   │   │   │   │   └── text.t
│   │   │   │   │   ├── magic_link/
│   │   │   │   │   │   ├── html.t
│   │   │   │   │   │   ├── subject.t
│   │   │   │   │   │   └── text.t
│   │   │   │   │   └── welcome/
│   │   │   │   │       ├── html.t
│   │   │   │   │       ├── subject.t
│   │   │   │   │       └── text.t
│   │   │   │   ├── auth.rs
│   │   │   │   └── mod.rs
│   │   │   ├── models/
│   │   │   │   ├── _entities/
│   │   │   │   │   ├── mod.rs.t
│   │   │   │   │   ├── prelude.rs.t
│   │   │   │   │   └── users.rs
│   │   │   │   ├── mod.rs.t
│   │   │   │   └── users.rs
│   │   │   ├── tasks/
│   │   │   │   ├── mod.rs.t
│   │   │   │   └── user_create.rs
│   │   │   ├── views/
│   │   │   │   ├── auth.rs
│   │   │   │   ├── home.rs
│   │   │   │   └── mod.rs.t
│   │   │   └── workers/
│   │   │       ├── downloader.rs
│   │   │       └── mod.rs.t
│   │   └── tests/
│   │       ├── mod.rs.t
│   │       ├── models/
│   │       │   ├── mod.rs.t
│   │       │   ├── snapshots/
│   │       │   │   ├── can_create_with_password@users.snap
│   │       │   │   ├── can_find_by_email@users-2.snap
│   │       │   │   ├── can_find_by_email@users.snap
│   │       │   │   ├── can_find_by_pid@users-2.snap
│   │       │   │   ├── can_find_by_pid@users.snap
│   │       │   │   ├── can_validate_model@users.snap
│   │       │   │   └── handle_create_with_password_with_duplicate@users.snap
│   │       │   └── users.rs.t
│   │       ├── requests/
│   │       │   ├── auth.rs.t
│   │       │   ├── home.rs.t
│   │       │   ├── mod.rs.t
│   │       │   ├── prepare_data.rs.t
│   │       │   └── snapshots/
│   │       │       ├── can_auth_with_magic_link@auth_request.snap
│   │       │       ├── can_get_current_user@auth_request.snap
│   │       │       ├── can_login_without_verify@auth_request.snap
│   │       │       ├── can_register@auth_request.snap
│   │       │       ├── can_reset_password@auth_request.snap
│   │       │       ├── login_with_invalid_password@auth_request.snap
│   │       │       ├── login_with_valid_password@auth_request.snap
│   │       │       └── resend_verification_user@auth_request.snap
│   │       ├── tasks/
│   │       │   ├── mod.rs.t
│   │       │   └── user_create.rs.t
│   │       └── workers/
│   │           └── mod.rs
│   ├── devnew.sh
│   ├── setup.rhai
│   ├── src/
│   │   ├── bin/
│   │   │   └── main.rs
│   │   ├── generator/
│   │   │   ├── executer/
│   │   │   │   ├── filesystem.rs
│   │   │   │   ├── inmem.rs
│   │   │   │   └── mod.rs
│   │   │   ├── mod.rs
│   │   │   └── template.rs
│   │   ├── lib.rs
│   │   ├── settings.rs
│   │   └── wizard.rs
│   └── tests/
│       ├── assertion/
│       │   ├── mod.rs
│       │   ├── string.rs
│       │   ├── toml.rs
│       │   └── yaml.rs
│       ├── mod.rs
│       ├── templates/
│       │   ├── asset.rs
│       │   ├── auth.rs
│       │   ├── background.rs
│       │   ├── db.rs
│       │   ├── features.rs
│       │   ├── initializers.rs
│       │   ├── mailer.rs
│       │   ├── mod.rs
│       │   ├── module_name.rs
│       │   └── snapshots/
│       │       ├── r#mod__templates__asset__cargo_dependencies_Clientside.snap
│       │       ├── r#mod__templates__asset__cargo_dependencies_None.snap
│       │       ├── r#mod__templates__asset__cargo_dependencies_Serverside.snap
│       │       ├── r#mod__templates__auth__src_app_rs_auth_false_None.snap
│       │       ├── r#mod__templates__auth__src_app_rs_auth_false_Sqlite.snap
│       │       ├── r#mod__templates__auth__src_app_rs_auth_true_None.snap
│       │       ├── r#mod__templates__auth__src_app_rs_auth_true_Sqlite.snap
│       │       ├── r#mod__templates__background__src_app_rs_Async.snap
│       │       ├── r#mod__templates__background__src_app_rs_Blocking.snap
│       │       ├── r#mod__templates__background__src_app_rs_None.snap
│       │       ├── r#mod__templates__background__src_app_rs_Queue.snap
│       │       ├── r#mod__templates__db__cargo_dependencies_None.snap
│       │       ├── r#mod__templates__db__cargo_dependencies_Postgres.snap
│       │       ├── r#mod__templates__db__cargo_dependencies_Sqlite.snap
│       │       ├── r#mod__templates__db__config_development_yaml_config_database_Postgres.snap
│       │       ├── r#mod__templates__db__config_development_yaml_config_database_Sqlite.snap
│       │       ├── r#mod__templates__db__config_test_yaml_config_database_Postgres.snap
│       │       ├── r#mod__templates__db__config_test_yaml_config_database_Sqlite.snap
│       │       ├── r#mod__templates__db__src_app_rs_None.snap
│       │       ├── r#mod__templates__db__src_app_rs_Postgres.snap
│       │       ├── r#mod__templates__db__src_app_rs_Sqlite.snap
│       │       ├── r#mod__templates__initializers__src_app_rs_with_initializers.snap
│       │       ├── r#mod__templates__initializers__src_app_rs_without_initializers.snap
│       │       ├── r#mod__templates__mailer__cargo_dependencies_mailer_false.snap
│       │       └── r#mod__templates__mailer__cargo_dependencies_mailer_true.snap
│       └── wizard/
│           ├── mod.rs
│           └── new.rs
├── snipdoc.yml
├── src/
│   ├── app.rs
│   ├── auth/
│   │   ├── jwt.rs
│   │   ├── mod.rs
│   │   └── snapshots/
│   │       ├── loco_rs__auth__jwt__tests__token expired.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom array claims.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom boolean claims.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom nested array claims.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom nested claims.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom number claims.snap
│   │       ├── loco_rs__auth__jwt__tests__valid token and custom string claims.snap
│   │       └── loco_rs__auth__jwt__tests__valid token.snap
│   ├── banner.rs
│   ├── bgworker/
│   │   ├── mod.rs
│   │   ├── pg.rs
│   │   ├── redis.rs
│   │   ├── snapshots/
│   │   │   ├── loco_rs__bgworker__pg__tests__can_complete_job_with_interval.snap
│   │   │   ├── loco_rs__bgworker__pg__tests__can_dequeue.snap
│   │   │   ├── loco_rs__bgworker__pg__tests__can_enqueue.snap
│   │   │   ├── loco_rs__bgworker__pg__tests__can_fail_job.snap
│   │   │   ├── loco_rs__bgworker__pg__tests__can_initialize_database.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__can_complete_job_with_interval.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__can_dequeue.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__can_enqueue.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__can_fail_job.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__sqlt_loco_queue.snap
│   │   │   ├── loco_rs__bgworker__sqlt__tests__sqlt_loco_queue_lock.snap
│   │   │   └── loco_rs__bgworker__tests__can_dump_jobs.snap
│   │   └── sqlt.rs
│   ├── boot.rs
│   ├── cache/
│   │   ├── drivers/
│   │   │   ├── inmem.rs
│   │   │   ├── mod.rs
│   │   │   ├── null.rs
│   │   │   └── redis.rs
│   │   └── mod.rs
│   ├── cargo_config.rs
│   ├── cli.rs
│   ├── config.rs
│   ├── controller/
│   │   ├── app_routes.rs
│   │   ├── backtrace.rs
│   │   ├── describe.rs
│   │   ├── extractor/
│   │   │   ├── auth.rs
│   │   │   ├── mod.rs
│   │   │   ├── shared_store.rs
│   │   │   ├── snapshots/
│   │   │   │   ├── loco_rs__controller__extractor__auth__tests__extract_from_bearer.snap
│   │   │   │   ├── loco_rs__controller__extractor__auth__tests__extract_from_cookie.snap
│   │   │   │   ├── loco_rs__controller__extractor__auth__tests__extract_from_default.snap
│   │   │   │   ├── loco_rs__controller__extractor__auth__tests__extract_from_multiple_locations.snap
│   │   │   │   └── loco_rs__controller__extractor__auth__tests__extract_from_query.snap
│   │   │   └── validate.rs
│   │   ├── format.rs
│   │   ├── middleware/
│   │   │   ├── _archive/
│   │   │   │   └── content_etag.rs
│   │   │   ├── catch_panic.rs
│   │   │   ├── compression.rs
│   │   │   ├── cors.rs
│   │   │   ├── etag.rs
│   │   │   ├── fallback.html
│   │   │   ├── fallback.rs
│   │   │   ├── format.rs
│   │   │   ├── limit_payload.rs
│   │   │   ├── logger.rs
│   │   │   ├── mod.rs
│   │   │   ├── powered_by.rs
│   │   │   ├── remote_ip.rs
│   │   │   ├── request_id.rs
│   │   │   ├── secure_headers.json
│   │   │   ├── secure_headers.rs
│   │   │   ├── snapshots/
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_OPTIONS_[allow_origins].snap
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_[default].snap
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_[with_allow_headers].snap
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_[with_allow_methods].snap
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_[with_expose_headers].snap
│   │   │   │   ├── loco_rs__controller__middleware__cors__tests__cors_[with_max_age].snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-2.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-3.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-4.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-5.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-6.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-7.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing-8.snap
│   │   │   │   ├── loco_rs__controller__middleware__remote_ip__tests__parsing.snap
│   │   │   │   ├── loco_rs__controller__middleware__request_id__tests__create_or_fetch_request_id-2.snap
│   │   │   │   ├── loco_rs__controller__middleware__request_id__tests__create_or_fetch_request_id-3.snap
│   │   │   │   ├── loco_rs__controller__middleware__request_id__tests__create_or_fetch_request_id-4.snap
│   │   │   │   ├── loco_rs__controller__middleware__request_id__tests__create_or_fetch_request_id-5.snap
│   │   │   │   ├── loco_rs__controller__middleware__request_id__tests__create_or_fetch_request_id.snap
│   │   │   │   ├── loco_rs__controller__middleware__secure_headers__tests__can_override_headers.snap
│   │   │   │   ├── loco_rs__controller__middleware__secure_headers__tests__can_set_headers.snap
│   │   │   │   └── loco_rs__controller__middleware__secure_headers__tests__default_is_github_preset.snap
│   │   │   ├── static_assets.rs
│   │   │   ├── static_assets_embedded.rs
│   │   │   └── timeout.rs
│   │   ├── mod.rs
│   │   ├── monitoring.rs
│   │   ├── routes.rs
│   │   ├── snapshots/
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]_health].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]_ping].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]_readiness].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]api[slash]loco-rs].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]api[slash]loco].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]api[slash]v1[slash]notes].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]api[slash]v1[slash]users].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]multiple1].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]multiple2].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]multiple3].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]normalizer[slash]loco[slash]rs].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]normalizer[slash]multiple-end].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]normalizer[slash]multiple-start].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]normalizer[slash]no-slash].snap
│   │   │   ├── loco_rs__controller__app_routes__tests__[[slash]normalizer].snap
│   │   │   ├── loco_rs__controller__format__tests__builder_cookies_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_empty_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_html_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_json_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_redirect_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_redirect_with_custom_header_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_template_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_text_response.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_view_response-2.snap
│   │   │   ├── loco_rs__controller__format__tests__builder_view_response.snap
│   │   │   ├── loco_rs__controller__format__tests__empty_json_response_format.snap
│   │   │   ├── loco_rs__controller__format__tests__empty_response_format.snap
│   │   │   ├── loco_rs__controller__format__tests__html_response_format.snap
│   │   │   ├── loco_rs__controller__format__tests__json_response_format.snap
│   │   │   ├── loco_rs__controller__format__tests__redirect_response.snap
│   │   │   ├── loco_rs__controller__format__tests__template_response.snap
│   │   │   ├── loco_rs__controller__format__tests__text_response_format.snap
│   │   │   ├── loco_rs__controller__format__tests__view_response-2.snap
│   │   │   ├── loco_rs__controller__format__tests__view_response.snap
│   │   │   └── loco_rs__controller__format__tests__yaml_response_format.snap
│   │   └── views/
│   │       ├── engine.rs
│   │       ├── engine_embedded.rs
│   │       ├── mod.rs
│   │       ├── pagination.rs
│   │       └── tera_builtins/
│   │           ├── filters/
│   │           │   ├── mod.rs
│   │           │   └── number.rs
│   │           └── mod.rs
│   ├── data.rs
│   ├── db.rs
│   ├── depcheck.rs
│   ├── doctor.rs
│   ├── env_vars.rs
│   ├── environment.rs
│   ├── errors.rs
│   ├── hash.rs
│   ├── initializers/
│   │   ├── extra_db.rs
│   │   ├── mod.rs
│   │   └── multi_db.rs
│   ├── lib.rs
│   ├── logger.rs
│   ├── mailer/
│   │   ├── email_sender.rs
│   │   ├── mod.rs
│   │   ├── snapshots/
│   │   │   ├── loco_rs__mailer__email_sender__tests__can_send_email.snap
│   │   │   ├── loco_rs__mailer__email_sender__tests__can_send_email_with_custom_headers.snap
│   │   │   └── loco_rs__mailer__template__tests__can_render_template.snap
│   │   └── template.rs
│   ├── model/
│   │   ├── mod.rs
│   │   └── query/
│   │       ├── dsl/
│   │       │   ├── date_range.rs
│   │       │   └── mod.rs
│   │       ├── mod.rs
│   │       └── paginate/
│   │           └── mod.rs
│   ├── prelude.rs
│   ├── scheduler.rs
│   ├── schema.rs
│   ├── snapshots/
│   │   ├── loco_rs__auth__tests__token expired.snap
│   │   ├── loco_rs__auth__tests__valid token.snap
│   │   ├── loco_rs__db__tests__dump_tables_sqlite_all_types.snap
│   │   ├── loco_rs__db__tests__dump_tables_sqlite_all_types_roundtrip.snap
│   │   ├── loco_rs__scheduler__tests__can_display_scheduler.snap
│   │   ├── loco_rs__scheduler__tests__can_prepare_command_[shell].snap
│   │   ├── loco_rs__scheduler__tests__can_prepare_command_[task].snap
│   │   ├── loco_rs__validation__tests__struct-[foo-bar].snap
│   │   ├── loco_rs__validation__tests__struct-[foo].snap
│   │   ├── loco_rs__worker__tests__default_custom_queues-2.snap
│   │   ├── loco_rs__worker__tests__default_custom_queues-3.snap
│   │   └── loco_rs__worker__tests__default_custom_queues.snap
│   ├── storage/
│   │   ├── contents.rs
│   │   ├── drivers/
│   │   │   ├── aws.rs
│   │   │   ├── azure.rs
│   │   │   ├── gcp.rs
│   │   │   ├── local.rs
│   │   │   ├── mem.rs
│   │   │   ├── mod.rs
│   │   │   ├── null.rs
│   │   │   └── opendal_adapter.rs
│   │   ├── mod.rs
│   │   ├── strategies/
│   │   │   ├── backup.rs
│   │   │   ├── mirror.rs
│   │   │   ├── mod.rs
│   │   │   └── single.rs
│   │   └── stream.rs
│   ├── task.rs
│   ├── tera.rs
│   ├── testing/
│   │   ├── db.rs
│   │   ├── mod.rs
│   │   ├── prelude.rs
│   │   ├── redaction.rs
│   │   ├── request.rs
│   │   └── selector.rs
│   ├── tests_cfg/
│   │   ├── app.rs
│   │   ├── config.rs
│   │   ├── controllers/
│   │   │   ├── auth.rs
│   │   │   ├── home.rs
│   │   │   └── mod.rs
│   │   ├── db.rs
│   │   ├── mod.rs
│   │   ├── postgres.rs
│   │   ├── queue.rs
│   │   ├── redis.rs
│   │   └── task.rs
│   └── validation.rs
├── tests/
│   ├── build_scripts/
│   │   ├── embedded_assets.rs
│   │   ├── mod.rs
│   │   └── snapshots/
│   │       ├── r#mod__build_scripts__embedded_assets__build_static_assets_static.snap
│   │       ├── r#mod__build_scripts__embedded_assets__build_static_assets_templates.snap
│   │       ├── r#mod__build_scripts__embedded_assets__collected_all_files.snap
│   │       ├── r#mod__build_scripts__embedded_assets__collected_css_files.snap
│   │       ├── r#mod__build_scripts__embedded_assets__complex_template_inheritance.snap
│   │       ├── r#mod__build_scripts__embedded_assets__discovered_directories.snap
│   │       ├── r#mod__build_scripts__embedded_assets__empty_static_assets_rs.snap
│   │       ├── r#mod__build_scripts__embedded_assets__empty_templates_rs.snap
│   │       ├── r#mod__build_scripts__embedded_assets__static_assets_rs.snap
│   │       ├── r#mod__build_scripts__embedded_assets__template_inheritance.snap
│   │       └── r#mod__build_scripts__embedded_assets__view_templates_rs.snap
│   ├── controller/
│   │   ├── extractor/
│   │   │   ├── auth/
│   │   │   │   ├── api_token.rs
│   │   │   │   ├── jwt.rs
│   │   │   │   ├── jwt_with_user.rs
│   │   │   │   └── mod.rs
│   │   │   ├── mod.rs
│   │   │   ├── shared_store.rs
│   │   │   └── validate.rs
│   │   ├── from_ref.rs
│   │   ├── into_response.rs
│   │   ├── middlewares.rs
│   │   ├── mod.rs
│   │   └── snapshots/
│   │       ├── cors_[default]@middlewares.snap
│   │       ├── cors_[disabled]@middlewares.snap
│   │       ├── cors_[with_allow_headers]@middlewares.snap
│   │       ├── cors_[with_allow_methods]@middlewares.snap
│   │       ├── cors_[with_max_age]@middlewares.snap
│   │       ├── panic@middlewares.snap
│   │       ├── secure_headers_[empty]_overrides[none]@middlewares.snap
│   │       ├── secure_headers_[github]_overrides[Content-Security-Policy]@middlewares.snap
│   │       └── secure_headers_[none]_overrides[none]@middlewares.snap
│   ├── fixtures/
│   │   ├── email_template/
│   │   │   └── test/
│   │   │       ├── html.t
│   │   │       ├── subject.t
│   │   │       └── text.t
│   │   └── queue/
│   │       └── jobs.yaml
│   ├── infra_cfg/
│   │   ├── mod.rs
│   │   └── server.rs
│   └── mod.rs
└── xtask/
    ├── .rustfmt.toml
    ├── Cargo.toml
    ├── README.md
    └── src/
        ├── bin/
        │   └── main.rs
        ├── bump_version.rs
        ├── ci.rs
        ├── errors.rs
        ├── lib.rs
        ├── out.rs
        ├── prompt.rs
        ├── utils.rs
        └── versions.rs
Download .txt
SYMBOL INDEX (2070 symbols across 177 files)

FILE: build.rs
  function main (line 4) | fn main() {
  function embedded_assets_main (line 15) | fn embedded_assets_main() {

FILE: build/embedded_assets.rs
  function build_static_assets (line 9) | pub fn build_static_assets(out_dir: &Path) {
  function find_app_directory (line 72) | pub fn find_app_directory(out_dir: &Path) -> Option<PathBuf> {
  function discover_all_directories (line 90) | pub fn discover_all_directories(app_root: &Path) -> Vec<PathBuf> {
  function recursively_collect_directories (line 113) | pub fn recursively_collect_directories(
  function collect_all_files (line 138) | pub fn collect_all_files(dir: &Path, assets_dir: &Path, all_files: &mut ...
  function generate_asset_code (line 181) | pub fn generate_asset_code(
  function generate_empty_asset_files (line 396) | pub fn generate_empty_asset_files(output_path: &Path) -> io::Result<()> {

FILE: docs-site/static/js/search.js
  function inputFocus (line 6) | function inputFocus(e) {
  function suggestionFocus (line 39) | function suggestionFocus(e) {
  function show_results (line 75) | function show_results() {
  function accept_suggestion (line 114) | function accept_suggestion() {
  function makeTeaser (line 134) | function makeTeaser(body, terms) {
  function substringByByte (line 251) | function substringByByte(str, maxLength) {
  function getByteByBinary (line 305) | function getByteByBinary(binaryCode) {
  function getByteByHex (line 315) | function getByteByHex(hexCode) {

FILE: loco-cli/src/bin/main.rs
  function main (line 1) | fn main() {

FILE: loco-gen/src/controller.rs
  function generate (line 7) | pub fn generate(

FILE: loco-gen/src/infer.rs
  type MigrationType (line 6) | pub enum MigrationType {
  type FieldType (line 15) | pub enum FieldType {
  function parse_field_type (line 24) | pub fn parse_field_type(ftype: &str) -> Result<FieldType> {
  function guess_migration_type (line 42) | pub fn guess_migration_type(migration_name: &str) -> MigrationType {
  function test_infer_create_table (line 86) | fn test_infer_create_table() {
  function test_infer_add_columns (line 96) | fn test_infer_add_columns() {
  function test_infer_remove_columns (line 106) | fn test_infer_remove_columns() {
  function test_infer_add_reference (line 116) | fn test_infer_add_reference() {
  function test_infer_create_join_table (line 126) | fn test_infer_create_join_table() {
  function test_infer_create_join_table_with_underscores (line 137) | fn test_infer_create_join_table_with_underscores() {
  function test_infer_create_join_table_complex_names (line 149) | fn test_infer_create_join_table_complex_names() {
  function test_infer_create_join_table_mixed_names (line 161) | fn test_infer_create_join_table_mixed_names() {
  function test_empty_migration (line 173) | fn test_empty_migration() {
  function test_infer_create_join_table_no_and_separator (line 181) | fn test_infer_create_join_table_no_and_separator() {
  function test_infer_create_join_table_empty_after_and (line 190) | fn test_infer_create_join_table_empty_after_and() {
  function test_infer_create_join_table_empty_before_and (line 199) | fn test_infer_create_join_table_empty_before_and() {
  function test_infer_create_join_table_multiple_ands (line 208) | fn test_infer_create_join_table_multiple_ands() {

FILE: loco-gen/src/lib.rs
  type GenerateResults (line 32) | pub struct GenerateResults {
  type Error (line 38) | pub enum Error {
    method msg (line 52) | pub fn msg(err: impl std::error::Error + Send + Sync + 'static) -> Self {
  type Result (line 57) | pub type Result<T> = std::result::Result<T, Error>;
  type FieldType (line 60) | struct FieldType {
  type RustType (line 71) | pub enum RustType {
  type Mappings (line 77) | pub struct Mappings {
    method error_unrecognized_default_field (line 81) | fn error_unrecognized_default_field(&self, field: &str) -> Error {
    method error_unrecognized (line 85) | fn error_unrecognized(field: &str, allow_fields: &[&String]) -> Error {
    method rust_field_with_params (line 102) | pub fn rust_field_with_params(&self, field: &str, params: &Vec<String>...
    method rust_field_kind (line 130) | pub fn rust_field_kind(&self, field: &str) -> Result<&RustType> {
    method rust_field (line 143) | pub fn rust_field(&self, field: &str) -> Result<&str> {
    method schema_field (line 163) | pub fn schema_field(&self, field: &str) -> Result<&str> {
    method col_type_field (line 176) | pub fn col_type_field(&self, field: &str) -> Result<&str> {
    method col_type_arity (line 189) | pub fn col_type_arity(&self, field: &str) -> Result<usize> {
    method all_names (line 198) | pub fn all_names(&self) -> Vec<&String> {
  function get_mappings (line 210) | pub fn get_mappings() -> &'static Mappings {
  type ScaffoldKind (line 218) | pub enum ScaffoldKind {
  type DeploymentKind (line 225) | pub enum DeploymentKind {
  type Component (line 237) | pub enum Component {
  type AppInfo (line 306) | pub struct AppInfo {
  function new_generator (line 311) | pub fn new_generator() -> RRgen {
  function generate (line 320) | pub fn generate(rrgen: &RRgen, component: Component, appinfo: &AppInfo) ...
  function render_template (line 400) | fn render_template(rrgen: &RRgen, template: &Path, vars: &Value) -> Resu...
  function collect_messages (line 431) | pub fn collect_messages(results: &GenerateResults) -> String {
  function copy_template (line 467) | pub fn copy_template(path: &Path, to: &Path) -> Result<Vec<PathBuf>> {
  function test_template_not_found (line 523) | fn test_template_not_found() {
  function test_copy_template_valid_folder_template (line 540) | fn test_copy_template_valid_folder_template() {
  function test_mapping (line 584) | fn test_mapping() -> Mappings {
  function can_get_all_names_from_mapping (line 610) | fn can_get_all_names_from_mapping() {
  function can_get_col_type_arity_from_mapping (line 619) | fn can_get_col_type_arity_from_mapping() {
  function can_get_col_type_field_from_mapping (line 634) | fn can_get_col_type_field_from_mapping() {
  function can_get_schema_field_from_mapping (line 646) | fn can_get_schema_field_from_mapping() {
  function can_get_rust_field_from_mapping (line 658) | fn can_get_rust_field_from_mapping() {
  function can_get_rust_field_kind_from_mapping (line 674) | fn can_get_rust_field_kind_from_mapping() {
  function can_get_rust_field_with_params_from_mapping (line 683) | fn can_get_rust_field_with_params_from_mapping() {
  function can_collect_messages (line 707) | fn can_collect_messages() {

FILE: loco-gen/src/migration.rs
  constant IGNORE_FIELDS (line 14) | pub const IGNORE_FIELDS: &[&str] = &["created_at", "updated_at", "create...
  function generate (line 16) | pub fn generate(

FILE: loco-gen/src/model.rs
  constant IGNORE_FIELDS (line 16) | pub const IGNORE_FIELDS: &[&str] = &["created_at", "updated_at", "create...
  function get_columns_and_references (line 23) | pub fn get_columns_and_references(
  function generate (line 99) | pub fn generate(
  function to_field (line 148) | fn to_field(name: &str, field_type: &str) -> (String, String) {
  function test_get_columns_with_field_types (line 153) | fn test_get_columns_with_field_types() {
  function test_get_columns_with_array_types (line 171) | fn test_get_columns_with_array_types() {
  function test_get_references_from_fields (line 190) | fn test_get_references_from_fields() {
  function test_ignore_fields_are_filtered_out (line 204) | fn test_ignore_fields_are_filtered_out() {
  function validate_arity (line 220) | fn validate_arity() {

FILE: loco-gen/src/scaffold.rs
  function generate (line 11) | pub fn generate(

FILE: loco-gen/src/template.rs
  constant DEFAULT_LOCAL_TEMPLATE (line 8) | pub const DEFAULT_LOCAL_TEMPLATE: &str = ".loco-templates";
  function get_ignored_paths (line 12) | pub fn get_ignored_paths() -> Vec<&'static Path> {
  function exists (line 25) | pub fn exists(path: &Path) -> bool {
  function is_path_ignored (line 32) | fn is_path_ignored(path: &Path, ignored_paths: &[&Path]) -> bool {
  function collect (line 40) | pub fn collect() -> Vec<PathBuf> {
  function collect_files (line 46) | pub fn collect_files() -> Vec<&'static File<'static>> {
  function collect_files_path (line 54) | pub fn collect_files_path(path: &Path) -> Result<Vec<PathBuf>> {
  function collect_files_from_path (line 72) | pub fn collect_files_from_path(path: &Path) -> Result<Vec<&File<'_>>> {
  function collect_files_path_recursively (line 88) | fn collect_files_path_recursively(dir: &Dir<'_>) -> Vec<PathBuf> {
  function collect_files_recursively (line 105) | fn collect_files_recursively<'a>(dir: &'a Dir<'a>) -> Vec<&'a File<'a>> {
  function find_first_dir (line 133) | pub fn find_first_dir() -> &'static Dir<'static> {
  function find_first_file (line 139) | pub fn find_first_file<'a>(dir: &'a Dir<'a>) -> Option<&'a File<'a>> {
  function test_get_ignored_paths (line 154) | fn test_get_ignored_paths() {
  function test_exists (line 169) | fn test_exists() {
  function test_collect (line 183) | fn test_collect() {
  function test_collect_files (line 192) | fn test_collect_files() {
  function test_is_path_ignored (line 201) | fn test_is_path_ignored() {

FILE: loco-gen/src/tera_ext.rs
  function new (line 6) | pub fn new() -> Tera {
  constant DEFAULT_INPUT_CLASS (line 13) | const DEFAULT_INPUT_CLASS: &str = "flex h-9 w-full rounded-md border bor...
  type FormField (line 15) | struct FormField;
    method call (line 20) | fn call(&self, args: &HashMap<String, Value>) -> tera::Result<Value> {
    method is_safe (line 279) | fn is_safe(&self) -> bool {
  type ViewField (line 16) | struct ViewField;
    method call (line 346) | fn call(&self, args: &HashMap<String, Value>) -> tera::Result<Value> {
    method is_safe (line 385) | fn is_safe(&self) -> bool {
  function input_group (line 284) | fn input_group(fname: &str, create_input: &str, edit_input: &str) -> Str...
  function input_string (line 299) | fn input_string(
  function input_number (line 313) | fn input_number<T>(
  function input_description (line 338) | fn input_description<S: AsRef<str>>(description: S) -> String {
  function can_render_form_field (line 398) | fn can_render_form_field() {
  function can_render_view_field (line 447) | fn can_render_view_field() {

FILE: loco-gen/src/testutil.rs
  type FileContent (line 16) | pub struct FileContent {
    method from_file (line 22) | pub fn from_file(file_path: &str) -> Result<Self, Box<dyn Error>> {
    method check_contains (line 28) | pub fn check_contains(&self, pattern: &str) -> Result<(), Box<dyn Erro...
    method assert_contains (line 37) | pub fn assert_contains(&self, pattern: &str) {
    method check_regex_match (line 43) | pub fn check_regex_match(&self, pattern: &str) -> Result<(), Box<dyn E...
    method assert_regex_match (line 55) | pub fn assert_regex_match(&self, pattern: &str) {
    method check_not_contains (line 61) | pub fn check_not_contains(&self, pattern: &str) -> Result<(), Box<dyn ...
    method assert_not_contains (line 71) | pub fn assert_not_contains(&self, pattern: &str) {
    method check_length (line 77) | pub fn check_length(&self, expected_length: usize) -> Result<(), Box<d...
    method assert_length (line 90) | pub fn assert_length(&self, expected_length: usize) {
    method check_syntax (line 96) | pub fn check_syntax(&self) -> Result<(), Box<dyn Error>> {
    method assert_syntax (line 105) | pub fn assert_syntax(&self) {
  function check_file (line 111) | pub fn check_file<F>(file_path: &str, assertions: F) -> Result<(), Box<d...
  function assert_file (line 121) | pub fn assert_file<F>(file_path: &str, assertions: F)
  function check_no_warnings (line 132) | pub fn check_no_warnings() -> Result<(), Box<dyn std::error::Error>> {
  function assert_no_warnings (line 146) | pub fn assert_no_warnings() {
  function check_cargo_check (line 150) | pub fn check_cargo_check() -> Result<(), Box<dyn Error>> {
  function assert_cargo_check (line 163) | pub fn assert_cargo_check() {
  function check_file_not_exists (line 167) | pub fn check_file_not_exists(file_path: &str) -> Result<(), Box<dyn std:...
  function assert_file_not_exists (line 175) | pub fn assert_file_not_exists(file_path: &str) {
  function check_file_exists (line 179) | pub fn check_file_exists(file_path: &str) -> Result<(), Box<dyn std::err...
  function assert_file_exists (line 187) | pub fn assert_file_exists(file_path: &str) {
  function check_dir_exists (line 191) | pub fn check_dir_exists(dir_path: &str) -> Result<(), Box<dyn std::error...
  function assert_dir_exists (line 199) | pub fn assert_dir_exists(dir_path: &str) {
  function check_single_file_match (line 205) | pub fn check_single_file_match<P: AsRef<Path>>(
  function assert_single_file_match (line 240) | pub fn assert_single_file_match<P: AsRef<Path>>(dir: P, pattern: &str) -...
  function with_temp_dir (line 244) | pub fn with_temp_dir<F>(f: F) -> Result<(), Box<dyn Error>>

FILE: loco-gen/tests/db.rs
  function test_migrations_flow (line 10) | fn test_migrations_flow(#[values("postgres", "sqlite")] db_kind: &str) {

FILE: loco-gen/tests/templates/controller.rs
  function can_generate (line 13) | fn can_generate(#[case] kind: ScaffoldKind) {

FILE: loco-gen/tests/templates/deployment.rs
  function can_generate_docker (line 7) | fn can_generate_docker(
  function can_generate_nginx (line 69) | fn can_generate_nginx() {

FILE: loco-gen/tests/templates/mailer.rs
  function can_generate (line 7) | fn can_generate() {

FILE: loco-gen/tests/templates/migration.rs
  function can_generate (line 70) | fn can_generate(
  function fail_when_migration_lib_not_exists (line 169) | fn fail_when_migration_lib_not_exists(#[case] component: Component) {

FILE: loco-gen/tests/templates/model.rs
  function can_generate (line 17) | fn can_generate() {
  function fail_when_migration_lib_not_exists (line 80) | fn fail_when_migration_lib_not_exists() {
  function fail_when_test_models_mod_not_exists (line 111) | fn fail_when_test_models_mod_not_exists() {

FILE: loco-gen/tests/templates/scaffold.rs
  function can_generate (line 13) | fn can_generate(#[case] kind: ScaffoldKind) {

FILE: loco-gen/tests/templates/scheduler.rs
  function can_generate (line 15) | fn can_generate() {

FILE: loco-gen/tests/templates/task.rs
  function can_generate (line 17) | fn can_generate() {

FILE: loco-gen/tests/templates/utils.rs
  constant MIGRATION_SRC_LIB (line 4) | pub const MIGRATION_SRC_LIB: &str = r"
  constant APP_ROUTS (line 23) | pub const APP_ROUTS: &str = r"
  constant APP_TASK (line 32) | pub const APP_TASK: &str = r"
  constant APP_WORKER (line 40) | pub const APP_WORKER: &str = r"
  function guess_file_by_time (line 47) | pub fn guess_file_by_time(path: &Path, file_format: &str, max_attempts: ...

FILE: loco-gen/tests/templates/worker.rs
  function can_generate (line 17) | fn can_generate() {

FILE: loco-new/base_template/migration/src/m20220101_000001_users.rs
  type Migration (line 5) | pub struct Migration;
  method up (line 9) | async fn up(&self, m: &SchemaManager) -> Result<(), DbErr> {
  method down (line 37) | async fn down(&self, m: &SchemaManager) -> Result<(), DbErr> {

FILE: loco-new/base_template/src/controllers/auth.rs
  function get_allow_email_domain_re (line 16) | fn get_allow_email_domain_re() -> &'static Regex {
  type ForgotParams (line 23) | pub struct ForgotParams {
  type ResetParams (line 28) | pub struct ResetParams {
  type MagicLinkParams (line 34) | pub struct MagicLinkParams {
  type ResendVerificationParams (line 39) | pub struct ResendVerificationParams {
  function register (line 46) | async fn register(
  function verify (line 77) | async fn verify(State(ctx): State<AppContext>, Path(token): Path<String>...
  function forgot (line 98) | async fn forgot(
  function reset (line 120) | async fn reset(State(ctx): State<AppContext>, Json(params): Json<ResetPa...
  function login (line 137) | async fn login(State(ctx): State<AppContext>, Json(params): Json<LoginPa...
  function current (line 162) | async fn current(auth: auth::JWT, State(ctx): State<AppContext>) -> Resu...
  function magic_link (line 181) | async fn magic_link(
  function magic_link_verify (line 208) | async fn magic_link_verify(
  function resend_verification_email (line 230) | async fn resend_verification_email(
  function routes (line 261) | pub fn routes() -> Routes {

FILE: loco-new/base_template/src/controllers/home.rs
  function current (line 6) | async fn current() -> Result<Response> {
  function routes (line 10) | pub fn routes() -> Routes {

FILE: loco-new/base_template/src/initializers/view_engine.rs
  constant I18N_DIR (line 11) | const I18N_DIR: &str = "assets/i18n";
  constant I18N_SHARED (line 12) | const I18N_SHARED: &str = "assets/i18n/shared.ftl";
  type ViewEngineInitializer (line 14) | pub struct ViewEngineInitializer;
  method name (line 18) | fn name(&self) -> String {
  method after_routes (line 22) | async fn after_routes(&self, router: AxumRouter, _ctx: &AppContext) -> R...

FILE: loco-new/base_template/src/mailers/auth.rs
  type AuthMailer (line 14) | pub struct AuthMailer {}
    method send_welcome (line 22) | pub async fn send_welcome(ctx: &AppContext, user: &users::Model) -> Re...
    method forgot_password (line 46) | pub async fn forgot_password(ctx: &AppContext, user: &users::Model) ->...
    method send_magic_link (line 70) | pub async fn send_magic_link(ctx: &AppContext, user: &users::Model) ->...

FILE: loco-new/base_template/src/models/_entities/users.rs
  type Model (line 8) | pub struct Model {
  type Relation (line 30) | pub enum Relation {}

FILE: loco-new/base_template/src/models/users.rs
  constant MAGIC_LINK_LENGTH (line 10) | pub const MAGIC_LINK_LENGTH: i8 = 32;
  constant MAGIC_LINK_EXPIRATION_MIN (line 11) | pub const MAGIC_LINK_EXPIRATION_MIN: i8 = 5;
  type LoginParams (line 14) | pub struct LoginParams {
  type RegisterParams (line 20) | pub struct RegisterParams {
  type Validator (line 27) | pub struct Validator {
  method validator (line 35) | fn validator(&self) -> Box<dyn Validate> {
  method before_save (line 45) | async fn before_save<C>(self, _db: &C, insert: bool) -> Result<Self, DbErr>
  method find_by_api_key (line 63) | async fn find_by_api_key(db: &DatabaseConnection, api_key: &str) -> Mode...
  method find_by_claims_key (line 67) | async fn find_by_claims_key(db: &DatabaseConnection, claims_key: &str) -...
  method find_by_email (line 78) | pub async fn find_by_email(db: &DatabaseConnection, email: &str) -> Mode...
  method find_by_verification_token (line 95) | pub async fn find_by_verification_token(
  method find_by_magic_token (line 115) | pub async fn find_by_magic_token(db: &DatabaseConnection, token: &str) -...
  method find_by_reset_token (line 151) | pub async fn find_by_reset_token(db: &DatabaseConnection, token: &str) -...
  method find_by_pid (line 168) | pub async fn find_by_pid(db: &DatabaseConnection, pid: &str) -> ModelRes...
  method find_by_api_key (line 186) | pub async fn find_by_api_key(db: &DatabaseConnection, api_key: &str) -> ...
  method verify_password (line 204) | pub fn verify_password(&self, password: &str) -> bool {
  method create_with_password (line 214) | pub async fn create_with_password(
  method generate_jwt (line 254) | pub fn generate_jwt(&self, secret: &str, expiration: u64) -> ModelResult...
  method set_email_verification_sent (line 271) | pub async fn set_email_verification_sent(
  method set_forgot_password_sent (line 292) | pub async fn set_forgot_password_sent(mut self, db: &DatabaseConnection)...
  method verified (line 307) | pub async fn verified(mut self, db: &DatabaseConnection) -> ModelResult<...
  method reset_password (line 321) | pub async fn reset_password(
  method create_magic_link (line 340) | pub async fn create_magic_link(mut self, db: &DatabaseConnection) -> Mod...
  method clear_magic_link (line 356) | pub async fn clear_magic_link(mut self, db: &DatabaseConnection) -> Mode...

FILE: loco-new/base_template/src/tasks/user_create.rs
  type UserCreate (line 8) | pub struct UserCreate;
  method task (line 11) | fn task(&self) -> TaskInfo {
  method run (line 17) | async fn run(&self, app_context: &AppContext, vars: &task::Vars) -> Resu...

FILE: loco-new/base_template/src/views/auth.rs
  type LoginResponse (line 6) | pub struct LoginResponse {
    method new (line 15) | pub fn new(user: &users::Model, token: &str) -> Self {
  type CurrentResponse (line 26) | pub struct CurrentResponse {
    method new (line 34) | pub fn new(user: &users::Model) -> Self {

FILE: loco-new/base_template/src/views/home.rs
  type HomeResponse (line 14) | pub struct HomeResponse {
    method new (line 5) | pub fn new(app_name: &str) -> Self {

FILE: loco-new/base_template/src/workers/downloader.rs
  type DownloadWorker (line 4) | pub struct DownloadWorker {
    method build (line 15) | fn build(ctx: &AppContext) -> Self {
    method perform (line 18) | async fn perform(&self, _args: DownloadWorkerArgs) -> Result<()> {
  type DownloadWorkerArgs (line 9) | pub struct DownloadWorkerArgs {

FILE: loco-new/src/bin/main.rs
  type Cli (line 21) | struct Cli {
  type Commands (line 31) | enum Commands {
  constant DEFAULT_OS (line 65) | const DEFAULT_OS: &str = "linux";
  constant DEFAULT_OS (line 67) | const DEFAULT_OS: &str = "windows";
  function main (line 70) | fn main() -> Result<()> {
  function is_a_git_repo (line 183) | pub fn is_a_git_repo(destination_path: &Path) -> Result<bool> {
  type CmdExit (line 207) | pub struct CmdExit {
    method error_with_message (line 214) | pub fn error_with_message<S: Into<String>>(msg: S) -> Self {
    method ok_with_message (line 222) | pub fn ok_with_message<S: Into<String>>(msg: S) -> Self {
    method exit (line 229) | pub fn exit(&self) {

FILE: loco-new/src/generator/executer/filesystem.rs
  type FileSystem (line 10) | pub struct FileSystem {
    method new (line 18) | pub fn new(from: &Path, to: &Path) -> Self {
    method with_template_engine (line 27) | pub fn with_template_engine(
    method render_and_rename_template_file (line 39) | fn render_and_rename_template_file(
  method copy_file (line 67) | fn copy_file(&self, path: &Path) -> super::Result<PathBuf> {
  method create_file (line 88) | fn create_file(&self, path: &Path, content: String) -> super::Result<Pat...
  method copy_dir (line 110) | fn copy_dir(&self, directory_path: &Path) -> super::Result<()> {
  method copy_template (line 124) | fn copy_template(&self, file_path: &Path, settings: &Settings) -> super:...
  method copy_template_dir (line 140) | fn copy_template_dir(&self, directory_path: &Path, settings: &Settings) ...
  function init_filesystem (line 176) | fn init_filesystem() -> (FileSystem, tree_fs::Tree) {
  function can_copy_file (line 190) | fn can_copy_file() {
  function can_copy_dir (line 203) | fn can_copy_dir() {
  function can_copy_template (line 223) | fn can_copy_template() {
  function can_copy_template_dir (line 243) | fn can_copy_template_dir() {

FILE: loco-new/src/generator/executer/inmem.rs
  type Inmem (line 10) | pub struct Inmem {
    method new (line 18) | pub fn new(source: &Path) -> Self {
    method with_template_engine (line 23) | pub fn with_template_engine(
    method get_file_content (line 34) | pub fn get_file_content(&self, path: &Path) -> Option<String> {
  method copy_file (line 43) | fn copy_file(&self, file_path: &Path) -> super::Result<PathBuf> {
  method create_file (line 52) | fn create_file(&self, path: &Path, content: String) -> super::Result<Pat...
  method copy_dir (line 60) | fn copy_dir(&self, directory_path: &Path) -> super::Result<()> {
  method copy_template (line 69) | fn copy_template(&self, file_path: &Path, settings: &Settings) -> super:...
  method copy_template_dir (line 93) | fn copy_template_dir(&self, _path: &Path, _data: &Settings) -> super::Re...
  function init_in_memory_store (line 104) | fn init_in_memory_store() -> (Inmem, Tree) {
  function can_copy_file (line 115) | fn can_copy_file() {
  function test_copy_directory (line 134) | fn test_copy_directory() {
  function can_copy_template_file (line 154) | fn can_copy_template_file() {

FILE: loco-new/src/generator/executer/mod.rs
  type Result (line 13) | pub type Result<T> = std::result::Result<T, Error>;
  type Error (line 16) | pub enum Error {
    method msg (line 31) | pub fn msg<S: Into<String>>(msg: S) -> Self {
  type Executer (line 37) | pub trait Executer: Send + Sync {
    method copy_file (line 44) | fn copy_file(&self, path: &Path) -> Result<PathBuf>;
    method create_file (line 52) | fn create_file(&self, path: &Path, content: String) -> Result<PathBuf>;
    method copy_dir (line 60) | fn copy_dir(&self, path: &Path) -> Result<()>;
    method copy_template (line 68) | fn copy_template(&self, path: &Path, data: &Settings) -> Result<()>;
    method copy_template_dir (line 77) | fn copy_template_dir(&self, path: &Path, data: &Settings) -> Result<()>;

FILE: loco-new/src/generator/mod.rs
  function extract_default_template (line 29) | pub fn extract_default_template() -> std::io::Result<tree_fs::Tree> {
  type Generator (line 40) | pub struct Generator {
    method new (line 46) | pub fn new(executer: Arc<dyn executer::Executer>, settings: settings::...
    method run (line 55) | pub fn run(&self) -> crate::Result<()> {
    method run_from_script (line 64) | pub fn run_from_script(&self, script: &str) -> crate::Result<()> {
    method copy_file (line 111) | pub fn copy_file(&mut self, path: &str) -> Result<(), Box<rhai::EvalAl...
    method create_file (line 129) | pub fn create_file(
    method copy_files (line 153) | pub fn copy_files(&mut self, paths: rhai::Array) -> Result<(), Box<rha...
    method copy_dir (line 175) | pub fn copy_dir(&mut self, path: &str) -> Result<(), Box<rhai::EvalAlt...
    method copy_dirs (line 191) | pub fn copy_dirs(&mut self, paths: rhai::Array) -> Result<(), Box<rhai...
    method copy_template (line 212) | pub fn copy_template(&mut self, path: &str) -> Result<(), Box<rhai::Ev...
    method copy_template_dir (line 231) | pub fn copy_template_dir(&mut self, path: &str) -> Result<(), Box<rhai...
  function is_client_side (line 253) | pub const fn is_client_side(rendering_method: &mut settings::Asset) -> b...
  function is_server_side (line 259) | pub const fn is_server_side(rendering_method: &mut settings::Asset) -> b...
  function can_copy_file (line 272) | pub fn can_copy_file() {
  function can_copy_files (line 288) | pub fn can_copy_files() {
  function can_copy_dir (line 317) | pub fn can_copy_dir() {
  function can_copy_dirs (line 333) | pub fn can_copy_dirs() {
  function can_copy_template (line 361) | pub fn can_copy_template() {
  function can_copy_template_dir (line 377) | pub fn can_copy_template_dir() {

FILE: loco-new/src/generator/template.rs
  constant TEMPLATE_EXTENSION (line 14) | const TEMPLATE_EXTENSION: &str = "t";
  function generate_random_string (line 16) | fn generate_random_string<R: Rng>(rng: &mut R, length: u64) -> String {
  type Template (line 24) | pub struct Template {
    method new (line 42) | pub fn new(rng: StdRng) -> Self {
    method is_template (line 52) | pub fn is_template(&self, path: &Path) -> bool {
    method register_filters (line 60) | fn register_filters(&self, tera_instance: &mut tera::Tera) {
    method render (line 89) | pub fn render(&self, template_content: &str, settings: &Settings) -> t...
    method strip_template_extension (line 111) | pub fn strip_template_extension(&self, path: &Path) -> std::io::Result...
  method default (line 29) | fn default() -> Self {
  function test_is_template (line 136) | fn test_is_template() {
  function test_render_template (line 150) | fn test_render_template() {
  function test_strip_template_extension (line 165) | fn test_strip_template_extension() {
  function can_create_random_string (line 184) | fn can_create_random_string() {

FILE: loco-new/src/lib.rs
  type Result (line 9) | pub type Result<T> = std::result::Result<T, Error>;
  constant LOCO_VERSION (line 12) | pub const LOCO_VERSION: &str = "0.16";
  type Error (line 15) | pub enum Error {
    method msg (line 35) | pub fn msg<S: Into<String>>(msg: S) -> Self {
  type OS (line 41) | pub enum OS {

FILE: loco-new/src/settings.rs
  type Settings (line 17) | pub struct Settings {
    method from_wizard (line 61) | pub fn from_wizard(package_name: &str, prompt_selection: &wizard::Sele...
  function from (line 32) | fn from(db_option: DBOption) -> Self {
  function from (line 44) | fn from(bg: BackgroundOption) -> Self {
  function from (line 50) | fn from(asset: AssetsOption) -> Self {
  method default (line 92) | fn default() -> Self {
  function get_loco_version_text (line 110) | fn get_loco_version_text() -> String {
  type Db (line 122) | pub struct Db {
  type Background (line 129) | pub struct Background {
  type Asset (line 135) | pub struct Asset {
  type Initializers (line 140) | pub struct Initializers {
  type Features (line 146) | pub struct Features {
    method disable_features (line 163) | pub fn disable_features() -> Self {
  method default (line 152) | fn default() -> Self {

FILE: loco-new/src/wizard.rs
  type Template (line 15) | pub enum Template {
  type OptionsList (line 30) | pub enum OptionsList {
  type DBOption (line 42) | pub enum DBOption {
    method enable (line 54) | pub const fn enable(&self) -> bool {
    method user_message (line 59) | pub fn user_message(&self) -> Option<String> {
    method endpoint_config (line 72) | pub const fn endpoint_config(&self) -> &str {
  type BackgroundOption (line 84) | pub enum BackgroundOption {
    method user_message (line 99) | pub fn user_message(&self) -> Option<String> {
    method prompt_view (line 118) | pub const fn prompt_view(&self) -> &str {
  type AssetsOption (line 130) | pub enum AssetsOption {
    method enable (line 145) | pub const fn enable(&self) -> bool {
    method user_message (line 150) | pub fn user_message(&self) -> Option<String> {
  type ArgsPlaceholder (line 166) | pub struct ArgsPlaceholder {
  type Selections (line 173) | pub struct Selections {
    method message (line 181) | pub fn message(&self) -> Vec<String> {
  function app_name (line 201) | pub fn app_name(name: Option<String>) -> crate::Result<String> {
  function warn_if_in_git_repo (line 227) | pub fn warn_if_in_git_repo() -> crate::Result<()> {
  function validate_app_name (line 243) | fn validate_app_name(app_name: &str) -> Result<(), &str> {
  function select_option (line 271) | fn select_option<T>(text: &str, options: &[T]) -> crate::Result<T>
  function start (line 287) | pub fn start(args: &ArgsPlaceholder) -> crate::Result<Selections> {
  function select_db (line 338) | fn select_db(args: &ArgsPlaceholder) -> crate::Result<DBOption> {
  function select_background (line 352) | fn select_background(
  function select_asset (line 370) | fn select_asset(args: &ArgsPlaceholder) -> crate::Result<AssetsOption> {

FILE: loco-new/tests/assertion/string.rs
  function load (line 7) | pub fn load(path: PathBuf) -> String {
  function assert_line_regex (line 11) | pub fn assert_line_regex(content: &str, expected: &str) {
  function assert_str_not_exists (line 23) | pub fn assert_str_not_exists(content: &str, expected: &str) {
  function assert_contains (line 32) | pub fn assert_contains(content: &str, expected: &str) {
  function assert_not_contains (line 43) | pub fn assert_not_contains(content: &str, unexpected: &str) {

FILE: loco-new/tests/assertion/toml.rs
  function load (line 7) | pub fn load(path: PathBuf) -> toml::Value {
  function assert_path_value_eq_string (line 12) | pub fn assert_path_value_eq_string(toml: &Value, path: &[&str], expected...
  function eq_path_value_eq_bool (line 17) | pub fn eq_path_value_eq_bool(toml: &Value, path: &[&str], expected: bool) {
  function assert_path_is_empty_array (line 22) | pub fn assert_path_is_empty_array(toml: &Value, path: &[&str]) {
  function assert_path_value_eq_array (line 37) | pub fn assert_path_value_eq_array(toml: &Value, path: &[&str], expected:...
  function assert_path_value_eq (line 44) | pub fn assert_path_value_eq(toml: &Value, path: &[&str], expected: &Valu...
  function assert_path_is_object (line 55) | pub fn assert_path_is_object(toml: &Value, path: &[&str]) {
  function get_keys_concatenated_as_string (line 65) | pub fn get_keys_concatenated_as_string(toml: &Value, path: &[&str]) -> O...
  function assert_path_is_empty (line 80) | pub fn assert_path_is_empty(toml: &Value, path: &[&str]) {
  function assert_path_exists (line 94) | pub fn assert_path_exists(toml: &Value, path: &[&str]) {
  function get_value_at_path (line 106) | pub fn get_value_at_path<'a>(toml: &'a Value, path: &[&str]) -> Option<&...

FILE: loco-new/tests/assertion/yaml.rs
  function load (line 7) | pub fn load(path: PathBuf) -> serde_yaml::Value {
  function assert_path_value_eq_string (line 13) | pub fn assert_path_value_eq_string(yml: &Value, path: &[&str], expected:...
  function assert_path_value_eq_bool (line 20) | pub fn assert_path_value_eq_bool(yml: &Value, path: &[&str], expected: b...
  function assert_path_value_eq_int (line 27) | pub fn assert_path_value_eq_int(yml: &Value, path: &[&str], expected: i6...
  function assert_path_value_eq_float (line 32) | pub fn assert_path_value_eq_float(yml: &Value, path: &[&str], expected: ...
  function assert_path_key_count (line 39) | pub fn assert_path_key_count(yml: &Value, path: &[&str], expected_count:...
  function assert_path_value_eq (line 56) | pub fn assert_path_value_eq(yml: &Value, path: &[&str], expected: &Value) {
  function assert_path_is_object (line 75) | pub fn assert_path_is_object(yml: &Value, path: &[&str]) {
  function get_keys_concatenated_as_string (line 85) | pub fn get_keys_concatenated_as_string(yml: &Value, path: &[&str]) -> Op...
  function assert_path_is_empty (line 102) | pub fn assert_path_is_empty(yml: &Value, path: &[&str]) {
  function assert_path_value_eq_mapping (line 118) | pub fn assert_path_value_eq_mapping(yml: &Value, path: &[&str], expected...
  function get_value_at_path (line 130) | pub fn get_value_at_path<'a>(yml: &'a Value, path: &[&str]) -> Option<&'...

FILE: loco-new/tests/templates/asset.rs
  function run_generator (line 7) | pub fn run_generator(asset: AssetsOption) -> TestGenerator {
  function test_config_file_middleware_when_asset_empty (line 17) | fn test_config_file_middleware_when_asset_empty(
  function test_config_file_middleware_asset_server (line 27) | fn test_config_file_middleware_asset_server(
  function test_config_file_middleware_asset_client (line 55) | fn test_config_file_middleware_asset_client(
  function test_cargo_toml (line 82) | fn test_cargo_toml(
  function test_github_ci_yaml (line 96) | fn test_github_ci_yaml(

FILE: loco-new/tests/templates/auth.rs
  function run_generator (line 7) | pub fn run_generator(enable_auth: bool, db: DBOption) -> TestGenerator {
  function test_config_file_without_auth (line 20) | fn test_config_file_without_auth(
  function test_config_file_with_auth (line 29) | fn test_config_file_with_auth(
  function test_config_file_development_rand_secret (line 40) | fn test_config_file_development_rand_secret() {
  function test_config_file_test_rand_secret (line 51) | fn test_config_file_test_rand_secret() {
  function test_app_rs (line 62) | fn test_app_rs(
  function test_src_controllers_mod_rs (line 74) | fn test_src_controllers_mod_rs(#[values(true, false)] auth: bool) {
  function test_src_views_mod_rs (line 87) | fn test_src_views_mod_rs(#[values(true, false)] auth: bool) {
  function test_tests_requests_mod_rs (line 100) | fn test_tests_requests_mod_rs(#[values(true, false)] auth: bool) {
  function test_migration_src_lib (line 114) | fn test_migration_src_lib(#[values(true)] auth: bool) {
  function test_models_mod_rs (line 129) | fn test_models_mod_rs(#[values(true)] auth: bool) {
  function test_models_entities_mod_rs (line 140) | fn test_models_entities_mod_rs(#[values(true)] auth: bool) {
  function test_models_entities_prelude_rs (line 151) | fn test_models_entities_prelude_rs(#[values(true)] auth: bool) {
  function test_tests_models_mod_rs (line 165) | fn test_tests_models_mod_rs(#[values(true, false)] auth: bool) {

FILE: loco-new/tests/templates/background.rs
  function run_generator (line 7) | pub fn run_generator(background: BackgroundOption) -> TestGenerator {
  function test_config_file_queue (line 17) | fn test_config_file_queue(
  function test_config_file_workers (line 61) | fn test_config_file_workers(
  function test_config_file_workers_tests (line 101) | fn test_config_file_workers_tests(
  function test_app_rs (line 140) | fn test_app_rs(
  function test_src_lib_rs (line 156) | fn test_src_lib_rs(
  function test_tests_mod_rs (line 173) | fn test_tests_mod_rs(

FILE: loco-new/tests/templates/db.rs
  function run_generator (line 7) | pub fn run_generator(db: DBOption) -> TestGenerator {
  function test_config_file_no_db (line 19) | fn test_config_file_no_db(
  function test_config_with_sqlite (line 28) | fn test_config_with_sqlite(
  function test_cargo_toml (line 49) | fn test_cargo_toml(#[values(DBOption::None, DBOption::Sqlite, DBOption::...
  function test_app_rs (line 60) | fn test_app_rs(#[values(DBOption::None, DBOption::Sqlite, DBOption::Post...
  function test_src_lib_rs (line 69) | fn test_src_lib_rs(#[values(DBOption::None, DBOption::Sqlite, DBOption::...
  function test_src_bin_main_rs (line 83) | fn test_src_bin_main_rs(
  function test_src_bin_tool_rs (line 105) | fn test_src_bin_tool_rs(
  function test_tests_mod_rs (line 126) | fn test_tests_mod_rs(#[values(DBOption::None, DBOption::Sqlite, DBOption...

FILE: loco-new/tests/templates/features.rs
  function run_generator (line 6) | pub fn run_generator(default_features: bool, names: &[&str]) -> TestGene...
  function test_cargo_toml_with_default_features_and_empty_names (line 19) | fn test_cargo_toml_with_default_features_and_empty_names() {
  function test_cargo_toml_without_default_features_and_empty_names (line 30) | fn test_cargo_toml_without_default_features_and_empty_names() {
  function test_cargo_toml_with_features (line 41) | fn test_cargo_toml_with_features() {
  function test_cargo_toml_without_features (line 55) | fn test_cargo_toml_without_features() {

FILE: loco-new/tests/templates/initializers.rs
  function run_generator (line 7) | pub fn run_generator(initializers: Option<settings::Initializers>) -> Te...
  function test_app_rs_with_initializers (line 17) | fn test_app_rs_with_initializers() {
  function test_app_rs_without_view_engine (line 26) | fn test_app_rs_without_view_engine() {
  function test_src_initializers_mod_rs_view_engine (line 35) | fn test_src_initializers_mod_rs_view_engine(#[values(true, false)] view_...

FILE: loco-new/tests/templates/mailer.rs
  function run_generator (line 7) | pub fn run_generator(enable_mailer: bool) -> TestGenerator {
  function test_config_file_without_mailer (line 17) | fn test_config_file_without_mailer(
  function test_config_file_with_mailer (line 26) | fn test_config_file_with_mailer(
  function test_cargo_toml (line 50) | fn test_cargo_toml(#[values(true, false)] mailer: bool) {
  function test_src_lib_rs (line 61) | fn test_src_lib_rs(#[values(true, false)] mailer: bool) {

FILE: loco-new/tests/templates/mod.rs
  type TestGenerator (line 21) | pub struct TestGenerator {
    method generate (line 26) | pub fn generate(settings: settings::Settings) -> Self {
    method path (line 47) | pub fn path(&self, path: &str) -> PathBuf {

FILE: loco-new/tests/templates/module_name.rs
  function run_generator (line 7) | pub fn run_generator() -> TestGenerator {
  function test_cargo_toml (line 18) | fn test_cargo_toml() {
  function test_use_name (line 39) | fn test_use_name(#[values("src/bin/main.rs", "tests/requests/home.rs")] ...
  function test_use_name_with_db (line 48) | fn test_use_name_with_db(
  function test_use_name_with_auth (line 68) | fn test_use_name_with_auth(#[values("tests/requests/auth.rs")] file: &st...

FILE: loco-new/tests/wizard/new.rs
  function test_starter_combinations (line 40) | fn test_starter_combinations(#[case] db: DBOption, #[case] asset: Assets...
  function test_combination (line 44) | fn test_combination(db: DBOption, asset: AssetsOption, test_generator: b...
  type Tester (line 197) | struct Tester {
    method run_clippy (line 203) | fn run_clippy(&self) -> Result<Output, std::io::Error> {
    method run_test (line 225) | fn run_test(&self) -> Result<Output, std::io::Error> {
    method run_migrate (line 234) | fn run_migrate(&self) -> Result<Output, std::io::Error> {
    method run_generate (line 243) | fn run_generate(&self, command: &Vec<&str>) {
    method run_generate_migration (line 265) | fn run_generate_migration(&self, command: &Vec<&str>) {

FILE: src/app.rs
  type SharedStore (line 35) | pub struct SharedStore {
    method insert (line 62) | pub fn insert<T: 'static + Send + Sync>(&self, val: T) {
    method remove (line 103) | pub fn remove<T: 'static + Send + Sync>(&self) -> Option<T> {
    method get_ref (line 151) | pub fn get_ref<T: 'static + Send + Sync>(&self) -> Option<RefGuard<'_,...
    method get (line 195) | pub fn get<T: 'static + Send + Sync + Clone>(&self) -> Option<T> {
    method contains (line 221) | pub fn contains<T: 'static + Send + Sync>(&self) -> bool {
  type RefGuard (line 228) | pub struct RefGuard<'a, T: 'static + Send + Sync> {
  type Target (line 234) | type Target = T;
  function deref (line 236) | fn deref(&self) -> &Self::Target {
  type AppContext (line 255) | pub struct AppContext {
  type Hooks (line 282) | pub trait Hooks: Send {
    method app_version (line 285) | fn app_version() -> String {
    method app_name (line 296) | fn app_name() -> &'static str;
    method boot (line 323) | async fn boot(mode: StartMode, environment: &Environment, config: Config)
    method serve (line 331) | async fn serve(app: AxumRouter, ctx: &AppContext, serve_params: &Serve...
    method init_logger (line 360) | fn init_logger(_ctx: &AppContext) -> Result<bool> {
    method load_config (line 368) | async fn load_config(env: &Environment) -> Result<Config> {
    method before_routes (line 378) | async fn before_routes(_ctx: &AppContext) -> Result<AxumRouter<AppCont...
    method after_routes (line 388) | async fn after_routes(router: AxumRouter, _ctx: &AppContext) -> Result...
    method initializers (line 395) | async fn initializers(_ctx: &AppContext) -> Result<Vec<Box<dyn Initial...
    method middlewares (line 401) | fn middlewares(ctx: &AppContext) -> Vec<Box<dyn MiddlewareLayer>> {
    method before_run (line 408) | async fn before_run(_app_context: &AppContext) -> Result<()> {
    method routes (line 413) | fn routes(_ctx: &AppContext) -> AppRoutes;
    method after_context (line 416) | async fn after_context(ctx: AppContext) -> Result<AppContext> {
    method connect_workers (line 422) | async fn connect_workers(ctx: &AppContext, queue: &Queue) -> Result<()>;
    method register_tasks (line 425) | fn register_tasks(tasks: &mut Tasks);
    method truncate (line 433) | async fn truncate(_ctx: &AppContext) -> Result<()>;
    method seed (line 437) | async fn seed(_ctx: &AppContext, path: &Path) -> Result<()>;
    method on_shutdown (line 442) | async fn on_shutdown(_ctx: &AppContext) {}
  type Initializer (line 453) | pub trait Initializer: Sync + Send {
    method name (line 455) | fn name(&self) -> String;
    method before_run (line 460) | async fn before_run(&self, _app_context: &AppContext) -> Result<()> {
    method after_routes (line 467) | async fn after_routes(&self, router: AxumRouter, _ctx: &AppContext) ->...
    method check (line 474) | async fn check(&self, _app_context: &AppContext) -> Result<Option<crat...
  type TestService (line 485) | struct TestService {
  type CloneableTestService (line 491) | struct CloneableTestService {
  function test_extensions_insert_and_get (line 497) | fn test_extensions_insert_and_get() {
  function test_extensions_get_without_clone (line 524) | fn test_extensions_get_without_clone() {
  function test_extensions_remove (line 558) | fn test_extensions_remove() {
  function test_extensions_contains (line 586) | fn test_extensions_contains() {
  function test_extensions_get_cloned (line 602) | fn test_extensions_get_cloned() {
  function test_app_context_extensions (line 642) | async fn test_app_context_extensions() {

FILE: src/auth/jwt.rs
  constant JWT_ALGORITHM (line 13) | const JWT_ALGORITHM: Algorithm = Algorithm::HS512;
  type UserClaims (line 18) | pub struct UserClaims {
  type JWT (line 34) | pub struct JWT {
    method new (line 42) | pub fn new(secret: &str) -> Self {
    method algorithm (line 51) | pub fn algorithm(mut self, algorithm: Algorithm) -> Self {
    method generate_token (line 70) | pub fn generate_token(
    method validate (line 102) | pub fn validate(&self, token: &str) -> JWTResult<TokenData<UserClaims>> {
  function can_generate_token (line 132) | fn can_generate_token(
  function serialize_user_claims (line 164) | fn serialize_user_claims(#[case] json_claims: Value) {
  function deserialize_user_claims (line 202) | fn deserialize_user_claims(#[case] json_claims: Value) {

FILE: src/banner.rs
  constant BANNER (line 5) | pub const BANNER: &str = r"
  function print_banner (line 23) | pub fn print_banner(boot_result: &BootResult, server_config: &ServeParam...

FILE: src/bgworker/mod.rs
  type JobStatus (line 31) | pub enum JobStatus {
    type Err (line 45) | type Err = String;
    method from_str (line 47) | fn from_str(s: &str) -> Result<Self, Self::Err> {
    method fmt (line 60) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Queue (line 66) | pub enum Queue {
    method enqueue (line 98) | pub async fn enqueue<A: Serialize + Send + Sync>(
    method register (line 148) | pub async fn register<
    method run (line 183) | pub async fn run(&self, tags: Vec<String>) -> Result<()> {
    method process_worker_handles (line 224) | async fn process_worker_handles(handles: Vec<tokio::task::JoinHandle<(...
    method setup (line 256) | pub async fn setup(&self) -> Result<()> {
    method clear (line 278) | pub async fn clear(&self) -> Result<()> {
    method ping (line 303) | pub async fn ping(&self) -> Result<()> {
    method describe (line 324) | pub fn describe(&self) -> String {
    method shutdown (line 340) | pub fn shutdown(&self) -> Result<()> {
    method get_jobs (line 355) | async fn get_jobs(
    method cancel_jobs (line 398) | pub async fn cancel_jobs(&self, job_name: &str) -> Result<()> {
    method clear_jobs_older_than (line 424) | pub async fn clear_jobs_older_than(
    method clear_by_status (line 459) | pub async fn clear_by_status(&self, status: Vec<JobStatus>) -> Result<...
    method requeue (line 483) | pub async fn requeue(&self, age_minutes: &i64) -> Result<()> {
    method dump (line 510) | pub async fn dump(
    method import (line 548) | pub async fn import(&self, path: &Path) -> Result<()> {
  type BackgroundWorker (line 588) | pub trait BackgroundWorker<A: Send + Sync + serde::Serialize + 'static>:...
    method queue (line 593) | fn queue() -> Option<String> {
    method tags (line 600) | fn tags() -> Vec<String> {
    method build (line 604) | fn build(ctx: &AppContext) -> Self;
    method class_name (line 606) | fn class_name() -> String
    method perform_later (line 615) | async fn perform_later(ctx: &AppContext, args: A) -> crate::Result<()>
    method perform (line 648) | async fn perform(&self, args: A) -> crate::Result<()>;
  function converge (line 656) | pub async fn converge(queue: &Queue, config: &QueueConfig) -> Result<()> {
  function create_queue_provider (line 702) | pub async fn create_queue_provider(config: &Config) -> Result<Option<Arc...
  function sqlite_config (line 748) | fn sqlite_config(db_path: &Path) -> SqliteQueueConfig {
  function can_dump_jobs (line 766) | async fn can_dump_jobs() {
  function cat_import_jobs_form_file (line 796) | async fn cat_import_jobs_form_file() {

FILE: src/bgworker/pg.rs
  type JobId (line 23) | type JobId = String;
  type JobData (line 24) | type JobData = JsonValue;
  type JobHandler (line 26) | type JobHandler = Box<
  type Job (line 36) | pub struct Job {
  type JobRegistry (line 49) | pub struct JobRegistry {
    method new (line 56) | pub fn new() -> Self {
    method register_worker (line 65) | pub fn register_worker<Args, W>(&mut self, name: String, worker: W) ->...
    method handlers (line 106) | pub fn handlers(&self) -> &Arc<HashMap<String, JobHandler>> {
    method run (line 112) | pub fn run(
  method default (line 206) | fn default() -> Self {
  function connect (line 211) | async fn connect(cfg: &PostgresQueueConfig) -> Result<PgPool> {
  function initialize_database (line 231) | pub async fn initialize_database(pool: &PgPool) -> Result<()> {
  function enqueue (line 259) | pub async fn enqueue(
  function dequeue (line 292) | async fn dequeue(client: &PgPool, worker_tags: &[String]) -> Result<Opti...
  function complete_job (line 356) | async fn complete_job(pool: &PgPool, id: &JobId, interval_ms: Option<i64...
  function fail_job (line 386) | async fn fail_job(pool: &PgPool, id: &JobId, error: &crate::Error) -> Re...
  function cancel_jobs_by_name (line 411) | pub async fn cancel_jobs_by_name(pool: &PgPool, name: &str) -> Result<()> {
  function clear (line 429) | pub async fn clear(pool: &PgPool) -> Result<()> {
  function clear_by_status (line 445) | pub async fn clear_by_status(pool: &PgPool, status: Vec<JobStatus>) -> R...
  function clear_jobs_older_than (line 468) | pub async fn clear_jobs_older_than(
  function requeue (line 506) | pub async fn requeue(pool: &PgPool, age_minutes: &i64) -> Result<()> {
  function ping (line 528) | pub async fn ping(pool: &PgPool) -> Result<()> {
  function get_jobs (line 546) | pub async fn get_jobs(
  function to_job (line 585) | fn to_job(row: &PgRow) -> Result<Job> {
  type RunOpts (line 619) | pub struct RunOpts {
  function create_provider (line 629) | pub async fn create_provider(qcfg: &PostgresQueueConfig) -> Result<Queue> {
  function reduction (line 659) | fn reduction() -> &'static [(&'static str, &'static str)] {
  type TableInfo (line 670) | pub struct TableInfo {
  function get_all_jobs (line 679) | async fn get_all_jobs(pool: &PgPool) -> Vec<Job> {
  function get_job (line 689) | async fn get_job(pool: &PgPool, id: &str) -> Job {
  function setup_pg_test (line 700) | async fn setup_pg_test() -> (
  function can_initialize_database (line 718) | async fn can_initialize_database() {
  function can_enqueue (line 733) | async fn can_enqueue() {
  function can_dequeue (line 769) | async fn can_dequeue() {
  function can_complete_job_without_interval (line 817) | async fn can_complete_job_without_interval() {
  function can_complete_job_with_interval (line 832) | async fn can_complete_job_with_interval() {
  function can_fail_job (line 860) | async fn can_fail_job() {
  function can_cancel_job_by_name (line 887) | async fn can_cancel_job_by_name() {
  function can_clear (line 913) | async fn can_clear() {
  function can_clear_by_status (line 934) | async fn can_clear_by_status() {
  function can_clear_jobs_older_than (line 977) | async fn can_clear_jobs_older_than() {
  function can_clear_jobs_older_than_with_status (line 996) | async fn can_clear_jobs_older_than_with_status() {
  function can_get_jobs (line 1023) | async fn can_get_jobs() {
  function can_get_jobs_with_age (line 1052) | async fn can_get_jobs_with_age() {
  function can_requeue (line 1079) | async fn can_requeue() {
  function can_handle_worker_panic (line 1128) | async fn can_handle_worker_panic() {
  function can_dequeue_with_tags (line 1192) | async fn can_dequeue_with_tags() {

FILE: src/bgworker/redis.rs
  type RedisPool (line 19) | pub type RedisPool = Client;
  type JobId (line 20) | type JobId = String;
  type JobData (line 21) | type JobData = JsonValue;
  constant QUEUE_KEY_PREFIX (line 23) | const QUEUE_KEY_PREFIX: &str = "queue:";
  constant JOB_KEY_PREFIX (line 24) | const JOB_KEY_PREFIX: &str = "job:";
  constant PROCESSING_KEY_PREFIX (line 25) | const PROCESSING_KEY_PREFIX: &str = "processing:";
  type JobHandler (line 27) | type JobHandler = Box<
  type Job (line 37) | pub struct Job {
    method new (line 52) | fn new(id: String, name: String, data: JsonValue) -> Self {
    method to_json (line 68) | fn to_json(&self) -> Result<String> {
    method from_json (line 73) | fn from_json(json: &str) -> Result<Self> {
  type JobRegistry (line 78) | pub struct JobRegistry {
    method new (line 85) | pub fn new() -> Self {
    method register_worker (line 96) | pub fn register_worker<Args, W>(&mut self, name: String, worker: W) ->...
    method handlers (line 135) | pub fn handlers(&self) -> &Arc<HashMap<String, JobHandler>> {
    method run (line 141) | pub fn run(
  method default (line 230) | fn default() -> Self {
  function connect (line 235) | fn connect(url: &str) -> Result<RedisPool> {
  function get_connection (line 240) | async fn get_connection(client: &RedisPool) -> Result<Connection> {
  function clear (line 250) | pub async fn clear(client: &RedisPool) -> Result<()> {
  function enqueue (line 261) | pub async fn enqueue(
  constant DEQUEUE_SCRIPT (line 293) | const DEQUEUE_SCRIPT: &str = r#"
  function dequeue_with_conn (line 310) | async fn dequeue_with_conn(
  function complete_job_with_conn (line 377) | async fn complete_job_with_conn(
  function fail_job_with_conn (line 411) | async fn fail_job_with_conn(
  function ping (line 440) | pub async fn ping(client: &RedisPool) -> Result<()> {
  function get_jobs (line 455) | pub async fn get_jobs(
  function should_include_job (line 518) | fn should_include_job(job: &Job, status: Option<&Vec<JobStatus>>, age_da...
  function clear_by_status (line 544) | pub async fn clear_by_status(client: &RedisPool, status: Vec<JobStatus>)...
  function clear_jobs_older_than (line 630) | pub async fn clear_jobs_older_than(
  function requeue (line 730) | pub async fn requeue(client: &RedisPool, age_minutes: &i64) -> Result<()> {
  function cancel_jobs_by_name (line 832) | pub async fn cancel_jobs_by_name(client: &RedisPool, job_name: &str) -> ...
  constant DEFAULT_QUEUES (line 870) | pub const DEFAULT_QUEUES: &[&str] = &["default", "mailer"];
  function get_queues (line 872) | pub fn get_queues(config_queues: &Option<Vec<String>>) -> Vec<String> {
  type RunOpts (line 887) | pub struct RunOpts {
  function create_provider (line 899) | pub async fn create_provider(qcfg: &RedisQueueConfig) -> Result<Queue> {
  function setup_redis (line 929) | async fn setup_redis() -> (RedisPool, ContainerAsync<GenericImage>) {
  function get_test_connection (line 935) | async fn get_test_connection(client: &RedisPool) -> Connection {
  function redis_seed_data (line 942) | async fn redis_seed_data(client: &RedisPool) -> Result<()> {
  function get_all_jobs (line 983) | async fn get_all_jobs(client: &RedisPool) -> Vec<Job> {
  function test_can_dequeue_redis (line 988) | async fn test_can_dequeue_redis() {
  function test_can_clear_redis (line 1004) | async fn test_can_clear_redis() {
  function test_can_enqueue_redis (line 1035) | async fn test_can_enqueue_redis() {
  function test_can_enqueue_with_queue_redis (line 1058) | async fn test_can_enqueue_with_queue_redis() {
  function test_can_complete_job_redis (line 1091) | async fn test_can_complete_job_redis() {
  function test_can_complete_job_with_interval_redis (line 1133) | async fn test_can_complete_job_with_interval_redis() {
  function test_can_fail_job_redis (line 1177) | async fn test_can_fail_job_redis() {
  function test_can_get_jobs_redis (line 1217) | async fn test_can_get_jobs_redis() {
  function test_job_registry_redis (line 1257) | async fn test_job_registry_redis() {
  function test_job_filtering_by_tags (line 1310) | async fn test_job_filtering_by_tags() {
  function test_ping_redis (line 1370) | async fn test_ping_redis() {
  function test_can_clear_by_status_redis (line 1376) | async fn test_can_clear_by_status_redis() {
  function test_can_clear_jobs_older_than_with_status_redis (line 1428) | async fn test_can_clear_jobs_older_than_with_status_redis() {
  function test_can_get_jobs_with_age_redis (line 1504) | async fn test_can_get_jobs_with_age_redis() {

FILE: src/bgworker/sqlt.rs
  type JobId (line 23) | type JobId = String;
  type JobData (line 24) | type JobData = JsonValue;
  type JobHandler (line 26) | type JobHandler = Box<
  type Job (line 36) | pub struct Job {
  type JobRegistry (line 49) | pub struct JobRegistry {
    method new (line 56) | pub fn new() -> Self {
    method register_worker (line 65) | pub fn register_worker<Args, W>(&mut self, name: String, worker: W) ->...
    method handlers (line 106) | pub fn handlers(&self) -> &Arc<HashMap<String, JobHandler>> {
    method run (line 112) | pub fn run(
  method default (line 204) | fn default() -> Self {
  function connect (line 209) | async fn connect(cfg: &SqliteQueueConfig) -> Result<SqlitePool> {
  function initialize_database (line 229) | pub async fn initialize_database(pool: &SqlitePool) -> Result<()> {
  function enqueue (line 266) | pub async fn enqueue(
  function dequeue (line 300) | async fn dequeue(client: &SqlitePool, worker_tags: &[String]) -> Result<...
  function complete_job (line 405) | async fn complete_job(pool: &SqlitePool, id: &JobId, interval_ms: Option...
  function fail_job (line 436) | async fn fail_job(pool: &SqlitePool, id: &JobId, error: &crate::Error) -...
  function cancel_jobs_by_name (line 461) | pub async fn cancel_jobs_by_name(pool: &SqlitePool, name: &str) -> Resul...
  function clear (line 480) | pub async fn clear(pool: &SqlitePool) -> Result<()> {
  function clear_by_status (line 503) | pub async fn clear_by_status(pool: &SqlitePool, status: Vec<JobStatus>) ...
  function requeue (line 529) | pub async fn requeue(pool: &SqlitePool, age_minutes: &i64) -> Result<()> {
  function clear_jobs_older_than (line 553) | pub async fn clear_jobs_older_than(
  function ping (line 587) | pub async fn ping(pool: &SqlitePool) -> Result<()> {
  type RunOpts (line 596) | pub struct RunOpts {
  function create_provider (line 606) | pub async fn create_provider(qcfg: &SqliteQueueConfig) -> Result<Queue> {
  function get_jobs (line 636) | pub async fn get_jobs(
  function to_job (line 674) | fn to_job(row: &SqliteRow) -> Result<Job> {
  type TableInfo (line 720) | pub struct TableInfo {
  type JobQueueLock (line 731) | struct JobQueueLock {
  function reduction (line 737) | fn reduction() -> &'static [(&'static str, &'static str)] {
  function init (line 744) | async fn init(db_path: &Path) -> Pool<Sqlite> {
  function get_all_jobs (line 774) | async fn get_all_jobs(pool: &SqlitePool) -> Vec<Job> {
  function get_job (line 784) | async fn get_job(pool: &SqlitePool, id: &str) -> Job {
  function can_initialize_database (line 795) | async fn can_initialize_database() {
  function can_enqueue (line 816) | async fn can_enqueue() {
  function can_dequeue (line 868) | async fn can_dequeue() {
  function can_complete_job_without_interval (line 925) | async fn can_complete_job_without_interval() {
  function can_complete_job_with_interval (line 946) | async fn can_complete_job_with_interval() {
  function can_fail_job (line 979) | async fn can_fail_job() {
  function can_cancel_job_by_name (line 1012) | async fn can_cancel_job_by_name() {
  function can_clear (line 1044) | async fn can_clear() {
  function can_clear_by_status (line 1079) | async fn can_clear_by_status() {
  function can_clear_jobs_older_than (line 1128) | async fn can_clear_jobs_older_than() {
  function can_clear_jobs_older_than_with_status (line 1153) | async fn can_clear_jobs_older_than_with_status() {
  function can_get_jobs (line 1186) | async fn can_get_jobs() {
  function can_get_jobs_with_age (line 1220) | async fn can_get_jobs_with_age() {
  function can_requeue (line 1252) | async fn can_requeue() {
  function can_handle_worker_panic (line 1300) | async fn can_handle_worker_panic() {
  function can_dequeue_with_tags (line 1369) | async fn can_dequeue_with_tags() {

FILE: src/boot.rs
  type StartMode (line 37) | pub enum StartMode {
  type BootResult (line 53) | pub struct BootResult {
  type ServeParams (line 66) | pub struct ServeParams {
  function start (line 83) | pub async fn start<H: Hooks>(
  function start_queue_worker (line 143) | fn start_queue_worker(app_context: &AppContext, tags: Vec<String>) -> Re...
  function shutdown_and_await_queue_worker (line 159) | async fn shutdown_and_await_queue_worker(
  function run_task (line 180) | pub async fn run_task<H: Hooks>(
  function scheduler (line 202) | fn scheduler<H: Hooks>(
  function run_scheduler (line 242) | pub async fn run_scheduler<H: Hooks>(
  type RunDbCommand (line 263) | pub enum RunDbCommand {
  function run_db (line 296) | pub async fn run_db<H: Hooks, M: MigratorTrait>(
  function create_context (line 356) | pub async fn create_context<H: Hooks>(
  function create_app (line 398) | pub async fn create_app<H: Hooks, M: MigratorTrait>(
  function create_app (line 414) | pub async fn create_app<H: Hooks>(
  function run_app (line 432) | pub async fn run_app<H: Hooks>(mode: &StartMode, app_context: AppContext...
  function setup_routes (line 488) | async fn setup_routes<H: Hooks>(
  function register_workers (line 503) | async fn register_workers<H: Hooks>(app_context: &AppContext) -> Result<...
  function list_endpoints (line 518) | pub fn list_endpoints<H: Hooks>(ctx: &AppContext) -> Vec<ListRoutes> {
  function shutdown_signal (line 528) | pub async fn shutdown_signal() {
  type MiddlewareInfo (line 552) | pub struct MiddlewareInfo {
  function list_middlewares (line 559) | pub fn list_middlewares<H: Hooks>(ctx: &AppContext) -> Vec<MiddlewareInf...
  function create_mailer (line 572) | fn create_mailer(config: &config::Mailer) -> Result<Option<EmailSender>> {

FILE: src/cache/drivers/inmem.rs
  function new (line 23) | pub fn new(config: &InMemCacheConfig) -> crate::cache::Cache {
  type Inmem (line 33) | pub struct Inmem {
    method from (line 44) | pub fn from(cache: Cache<String, (Expiration, String)>) -> Box<dyn Cac...
  method ping (line 56) | async fn ping(&self) -> CacheResult<()> {
  method contains_key (line 65) | async fn contains_key(&self, key: &str) -> CacheResult<bool> {
  method get (line 74) | async fn get(&self, key: &str) -> CacheResult<Option<String>> {
  method insert (line 87) | async fn insert(&self, key: &str, value: &str) -> CacheResult<()> {
  method insert_with_expiry (line 102) | async fn insert_with_expiry(
  method remove (line 123) | async fn remove(&self, key: &str) -> CacheResult<()> {
  method clear (line 133) | async fn clear(&self) -> CacheResult<()> {
  type Expiration (line 140) | pub enum Expiration {
    method as_duration (line 147) | pub fn as_duration(&self) -> Option<Duration> {
  type InMemExpiry (line 155) | pub struct InMemExpiry;
    method expire_after_create (line 158) | fn expire_after_create(
  function create_test_config (line 173) | fn create_test_config() -> InMemCacheConfig {
  function ping_returns_pong_when_cache_is_accessible (line 178) | async fn ping_returns_pong_when_cache_is_accessible() {
  function is_contains_key (line 185) | async fn is_contains_key() {
  function can_get_key_value (line 194) | async fn can_get_key_value() {
  function can_remove_key (line 208) | async fn can_remove_key() {
  function can_clear (line 218) | async fn can_clear() {

FILE: src/cache/drivers/mod.rs
  type CacheDriver (line 18) | pub trait CacheDriver: Sync + Send {
    method ping (line 25) | async fn ping(&self) -> CacheResult<()>;
    method contains_key (line 33) | async fn contains_key(&self, key: &str) -> CacheResult<bool>;
    method get (line 41) | async fn get(&self, key: &str) -> CacheResult<Option<String>>;
    method insert (line 49) | async fn insert(&self, key: &str, value: &str) -> CacheResult<()>;
    method insert_with_expiry (line 58) | async fn insert_with_expiry(
    method remove (line 71) | async fn remove(&self, key: &str) -> CacheResult<()>;
    method clear (line 79) | async fn clear(&self) -> CacheResult<()>;

FILE: src/cache/drivers/null.rs
  type Null (line 16) | pub struct Null {}
  function new (line 24) | pub fn new() -> Box<dyn CacheDriver> {
  method ping (line 35) | async fn ping(&self) -> CacheResult<()> {
  method contains_key (line 46) | async fn contains_key(&self, _key: &str) -> CacheResult<bool> {
  method get (line 57) | async fn get(&self, _key: &str) -> CacheResult<Option<String>> {
  method insert (line 66) | async fn insert(&self, _key: &str, _value: &str) -> CacheResult<()> {
  method insert_with_expiry (line 78) | async fn insert_with_expiry(
  method remove (line 94) | async fn remove(&self, _key: &str) -> CacheResult<()> {
  method clear (line 105) | async fn clear(&self) -> CacheResult<()> {

FILE: src/cache/drivers/redis.rs
  function new (line 27) | pub async fn new(config: &RedisCacheConfig) -> CacheResult<crate::cache:...
  type Redis (line 39) | pub struct Redis {
    method from (line 50) | pub fn from(pool: Pool<RedisConnectionManager>) -> Box<dyn CacheDriver> {
  method ping (line 62) | async fn ping(&self) -> CacheResult<()> {
  method contains_key (line 75) | async fn contains_key(&self, key: &str) -> CacheResult<bool> {
  method get (line 85) | async fn get(&self, key: &str) -> CacheResult<Option<String>> {
  method insert (line 96) | async fn insert(&self, key: &str, value: &str) -> CacheResult<()> {
  method insert_with_expiry (line 109) | async fn insert_with_expiry(
  method remove (line 127) | async fn remove(&self, key: &str) -> CacheResult<()> {
  method clear (line 138) | async fn clear(&self) -> CacheResult<()> {
  function setup_redis_driver (line 153) | async fn setup_redis_driver() -> (Box<dyn CacheDriver>, ContainerAsync<G...
  function ping_returns_pong_when_redis_is_reachable (line 172) | async fn ping_returns_pong_when_redis_is_reachable() {
  function test_contains_key (line 179) | async fn test_contains_key() {
  function test_get_key_value (line 199) | async fn test_get_key_value() {
  function test_remove_key (line 225) | async fn test_remove_key() {
  function test_clear (line 250) | async fn test_clear() {
  function test_expiry (line 279) | async fn test_expiry() {

FILE: src/cache/mod.rs
  type CacheError (line 18) | pub enum CacheError {
  type CacheResult (line 37) | pub type CacheResult<T> = std::result::Result<T, CacheError>;
  function create_cache_provider (line 45) | pub async fn create_cache_provider(config: &config::Config) -> crate::Re...
  type Cache (line 65) | pub struct Cache {
    method new (line 73) | pub fn new(driver: Box<dyn CacheDriver>) -> Self {
    method ping (line 93) | pub async fn ping(&self) -> CacheResult<()> {
    method contains_key (line 113) | pub async fn contains_key(&self, key: &str) -> CacheResult<bool> {
    method get (line 153) | pub async fn get<T: DeserializeOwned>(&self, key: &str) -> CacheResult...
    method insert (line 201) | pub async fn insert<T: Serialize + Sync + ?Sized>(
    method insert_with_expiry (line 250) | pub async fn insert_with_expiry<T: Serialize + Sync + ?Sized>(
    method get_or_insert (line 305) | pub async fn get_or_insert<T, F>(&self, key: &str, f: F) -> LocoResult<T>
    method get_or_insert_with_expiry (line 363) | pub async fn get_or_insert_with_expiry<T, F>(
    method remove (line 399) | pub async fn remove(&self, key: &str) -> CacheResult<()> {
    method clear (line 420) | pub async fn clear(&self) -> CacheResult<()> {
  function can_get_or_insert (line 432) | async fn can_get_or_insert() {
  type TestUser (line 452) | struct TestUser {
  function can_serialize_deserialize (line 458) | async fn can_serialize_deserialize() {
  function can_get_or_insert_generic (line 478) | async fn can_get_or_insert_generic() {

FILE: src/cargo_config.rs
  type CargoConfig (line 16) | pub struct CargoConfig {
    method from_current_dir (line 26) | pub fn from_current_dir() -> AppResult<Self> {
    method lock_from_current_dir (line 35) | pub fn lock_from_current_dir() -> AppResult<Self> {
    method from_path (line 44) | pub fn from_path(path: impl AsRef<Path>) -> AppResult<Self> {
    method get_db_entities (line 59) | pub fn get_db_entities(&self) -> Option<&Table> {
    method get_package_array (line 75) | pub fn get_package_array(&self) -> AppResult<&[toml::Value]> {
  type CwdGuard (line 89) | struct CwdGuard(PathBuf);
    method set_to (line 92) | fn set_to(path: &Path) -> Self {
  method drop (line 100) | fn drop(&mut self) {
  constant TEST_CARGO_TOML (line 105) | const TEST_CARGO_TOML: &str = r#"
  constant TEST_CARGO_LOCK (line 115) | const TEST_CARGO_LOCK: &str = r#"
  function setup_test_dir (line 133) | fn setup_test_dir(cargo_toml: Option<&str>) -> tree_fs::Tree {
  function setup_test_dir_with_lock (line 140) | fn setup_test_dir_with_lock(
  function test_from_path_valid_toml (line 152) | fn test_from_path_valid_toml() {
  function test_from_current_dir (line 162) | fn test_from_current_dir() {
  function test_lock_from_current_dir (line 171) | fn test_lock_from_current_dir() {
  function test_get_package_array (line 187) | fn test_get_package_array() {
  function test_get_db_entities (line 203) | fn test_get_db_entities() {
  function test_get_db_entities_no_config (line 216) | fn test_get_db_entities_no_config() {
  function test_invalid_toml (line 233) | fn test_invalid_toml() {
  function test_file_not_found (line 246) | fn test_file_not_found() {

FILE: src/cli.rs
  type Playground (line 46) | struct Playground {
  type Cli (line 55) | struct Cli {
  type Commands (line 65) | enum Commands {
  type ComponentArg (line 169) | enum ComponentArg {
    method into_gen_component (line 380) | fn into_gen_component(self, config: &Config) -> crate::Result<loco_gen...
  type DbCommands (line 478) | enum DbCommands {
  method from (line 520) | fn from(value: DbCommands) -> Self {
  type DeploymentKind (line 549) | pub enum DeploymentKind {
    method to_generator_component (line 556) | fn to_generator_component(&self, config: &Config) -> loco_gen::Compone...
  type JobsCommands (line 594) | enum JobsCommands {
  function parse_key_val (line 644) | fn parse_key_val<T, U>(
  function playground (line 665) | pub async fn playground<H: Hooks>() -> crate::Result<AppContext> {
  function main (line 706) | pub async fn main<H: Hooks, M: MigratorTrait>() -> crate::Result<()> {
  function main (line 856) | pub async fn main<H: Hooks>() -> crate::Result<()> {
  type RouteNode (line 993) | struct RouteNode {
    method is_leaf (line 999) | fn is_leaf(&self) -> bool {
    method is_collapsible (line 1003) | fn is_collapsible(&self) -> bool {
    method method (line 1009) | fn method(&self) -> &str {
    method print (line 1015) | fn print(&self, prefix: &str, segment: &str, is_last: bool, is_root: b...
    method print_endpoints (line 1078) | fn print_endpoints(&self, prefix: &str, is_last_group: bool, current_p...
    method print_children (line 1090) | fn print_children(&self, prefix: &str, current_path: &str) {
    method format_prefix (line 1108) | fn format_prefix(prefix: &str, is_last: bool, with_slash: bool) -> Str...
    method format_next_prefix (line 1117) | fn format_next_prefix(prefix: &str, is_last: bool) -> String {
    method build_path (line 1125) | fn build_path(segments: &[&str]) -> String {
    method print_with_format (line 1135) | fn print_with_format(tree: &str, method: &str, full_path: &str) {
  function show_list_endpoints (line 1140) | fn show_list_endpoints<H: Hooks>(ctx: &AppContext) {
  function color_method (line 1198) | fn color_method(method: &str) -> String {
  function create_root_span (line 1209) | fn create_root_span(environment: &Environment) -> tracing::Span {
  function handle_job_command (line 1214) | async fn handle_job_command<H: Hooks>(
  function handle_generate_command (line 1270) | fn handle_generate_command<H: Hooks>(
  function format_templates_as_tree (line 1328) | pub fn format_templates_as_tree(paths: Vec<PathBuf>) -> String {

FILE: src/config.rs
  function get_default_folder (line 39) | fn get_default_folder() -> &'static PathBuf {
  type Config (line 47) | pub struct Config {
    method new (line 599) | pub fn new(env: &Environment) -> Result<Self> {
    method from_folder (line 624) | pub fn from_folder(env: &Environment, path: &Path) -> Result<Self> {
    method get_jwt_config (line 651) | pub fn get_jwt_config(&self) -> Result<&JWT> {
    method fmt (line 663) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Logger (line 95) | pub struct Logger {
  type LoggerFileAppender (line 125) | pub struct LoggerFileAppender {
  type Database (line 182) | pub struct Database {
  type CacheConfig (line 247) | pub enum CacheConfig {
  type InMemCacheConfig (line 260) | pub struct InMemCacheConfig {
  function cache_in_mem_max_capacity (line 265) | fn cache_in_mem_max_capacity() -> u64 {
  type RedisCacheConfig (line 270) | pub struct RedisCacheConfig {
  type QueueConfig (line 278) | pub enum QueueConfig {
  type RedisQueueConfig (line 288) | pub struct RedisQueueConfig {
  type PostgresQueueConfig (line 302) | pub struct PostgresQueueConfig {
  type SqliteQueueConfig (line 331) | pub struct SqliteQueueConfig {
  function db_min_conn (line 359) | fn db_min_conn() -> u32 {
  function db_max_conn (line 363) | fn db_max_conn() -> u32 {
  function db_connect_timeout (line 367) | fn db_connect_timeout() -> u64 {
  function db_idle_timeout (line 371) | fn db_idle_timeout() -> u64 {
  function pgq_poll_interval (line 375) | fn pgq_poll_interval() -> u32 {
  function sqlt_poll_interval (line 379) | fn sqlt_poll_interval() -> u32 {
  function num_workers (line 383) | fn num_workers() -> u32 {
  type Auth (line 398) | pub struct Auth {
  type JWT (line 405) | pub struct JWT {
  type JWTLocation (line 421) | pub enum JWTLocation {
  type JWTLocationConfig (line 433) | pub enum JWTLocationConfig {
  type Server (line 465) | pub struct Server {
    method full_url (line 488) | pub fn full_url(&self) -> String {
  function default_binding (line 482) | fn default_binding() -> String {
  type Workers (line 500) | pub struct Workers {
  type WorkerMode (line 507) | pub enum WorkerMode {
  type Mailer (line 533) | pub struct Mailer {
  type Initializers (line 552) | pub type Initializers = BTreeMap<String, serde_json::Value>;
  type SmtpMailer (line 556) | pub struct SmtpMailer {
  type MailerAuth (line 572) | pub struct MailerAuth {

FILE: src/controller/app_routes.rs
  function get_normalize_url (line 18) | fn get_normalize_url() -> &'static Regex {
  type AppRoutes (line 24) | pub struct AppRoutes {
    method with_default_routes (line 52) | pub fn with_default_routes() -> Self {
    method empty (line 58) | pub fn empty() -> Self {
    method collect (line 66) | pub fn collect(&self) -> Vec<ListRoutes> {
    method get_prefix (line 105) | pub fn get_prefix(&self) -> Option<&String> {
    method get_routes (line 111) | pub fn get_routes(&self) -> &[Routes] {
    method prefix (line 128) | pub fn prefix(mut self, prefix: &str) -> Self {
    method nest_prefix (line 161) | pub fn nest_prefix(mut self, prefix: &str) -> Self {
    method nest_route (line 190) | pub fn nest_route(mut self, prefix: &str, route: Routes) -> Self {
    method nest_routes (line 221) | pub fn nest_routes(mut self, prefix: &str, routes: Vec<Routes>) -> Self {
    method add_route (line 232) | pub fn add_route(mut self, mut route: Routes) -> Self {
    method add_routes (line 255) | pub fn add_routes(mut self, mounts: Vec<Routes>) -> Self {
    method middlewares (line 264) | pub fn middlewares<H: Hooks>(&self, ctx: &AppContext) -> Vec<Box<dyn M...
    method to_router (line 278) | pub fn to_router<H: Hooks>(
  type ListRoutes (line 30) | pub struct ListRoutes {
    method fmt (line 37) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  function action (line 325) | async fn action() -> Result<Response> {
  function can_load_app_route_from_default (line 330) | fn can_load_app_route_from_default() {
  function can_load_empty_app_routes (line 342) | fn can_load_empty_app_routes() {
  function can_load_routes (line 347) | fn can_load_routes() {
  function can_load_routes_with_root_prefix (line 375) | fn can_load_routes_with_root_prefix() {
  function can_nest_prefix (line 393) | fn can_nest_prefix() {
  function can_nest_route (line 400) | fn can_nest_route() {
  function can_nest_routes (line 410) | fn can_nest_routes() {
  function can_request_method (line 436) | async fn can_request_method(

FILE: src/controller/backtrace.rs
  function get_name_blocklist (line 10) | fn get_name_blocklist() -> &'static Vec<Regex> {
  function get_file_blocklist (line 43) | fn get_file_blocklist() -> &'static Vec<Regex> {
  function print_backtrace (line 59) | pub fn print_backtrace(bt: &std::backtrace::Backtrace) -> Result<()> {

FILE: src/controller/describe.rs
  function get_describe_method_action (line 10) | fn get_describe_method_action() -> &'static Regex {
  function method_action (line 19) | pub fn method_action(method: &MethodRouter<AppContext>) -> Vec<http::Met...

FILE: src/controller/extractor/auth.rs
  constant TOKEN_PREFIX (line 45) | const TOKEN_PREFIX: &str = "Bearer ";
  constant AUTH_HEADER (line 46) | const AUTH_HEADER: &str = "authorization";
  type JWTWithUser (line 52) | pub struct JWTWithUser<T: Authenticable> {
  type Rejection (line 65) | type Rejection = Error;
  function from_request_parts (line 67) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self...
  type JWT (line 105) | pub struct JWT {
    type Rejection (line 115) | type Rejection = Error;
    method from_request_parts (line 117) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Se...
  function extract_jwt_from_request_parts (line 126) | pub fn extract_jwt_from_request_parts<S>(parts: &Parts, state: &S) -> Re...
  function get_jwt_from_config (line 152) | pub fn get_jwt_from_config(ctx: &AppContext) -> LocoResult<&JWTConfig> {
  function extract_token (line 167) | pub fn extract_token(jwt_config: &JWTConfig, parts: &Parts) -> LocoResul...
  function get_jwt_locations (line 181) | fn get_jwt_locations(
  function extract_token_from_location (line 192) | fn extract_token_from_location(
  function extract_token_from_header (line 208) | pub fn extract_token_from_header(headers: &HeaderMap) -> LocoResult<Stri...
  function extract_token_from_cookie (line 224) | pub fn extract_token_from_cookie(name: &str, parts: &Parts) -> LocoResul...
  function extract_token_from_query (line 239) | pub fn extract_token_from_query(name: &str, parts: &Parts) -> LocoResult...
  type ApiToken (line 257) | pub struct ApiToken<T: Authenticable> {
  type Rejection (line 270) | type Rejection = Error;
  function from_request_parts (line 273) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self...
  function test_extract_token_from_header_success (line 308) | fn test_extract_token_from_header_success() {
  function test_extract_token_from_header_with_spaces (line 321) | fn test_extract_token_from_header_with_spaces() {
  function test_extract_token_from_header_special_chars (line 334) | fn test_extract_token_from_header_special_chars() {
  function test_extract_token_from_header_missing_header (line 347) | fn test_extract_token_from_header_missing_header() {
  function test_extract_token_from_header_missing_bearer_prefix (line 358) | fn test_extract_token_from_header_missing_bearer_prefix() {
  function test_extract_token_from_header_empty_value (line 374) | fn test_extract_token_from_header_empty_value() {
  function test_extract_token_from_cookie_success (line 387) | fn test_extract_token_from_cookie_success() {
  function test_extract_token_from_cookie_special_chars (line 400) | fn test_extract_token_from_cookie_special_chars() {
  function test_extract_token_from_cookie_missing_cookie (line 413) | fn test_extract_token_from_cookie_missing_cookie() {
  function test_extract_token_from_cookie_not_found (line 426) | fn test_extract_token_from_cookie_not_found() {
  function test_extract_token_from_query_success (line 442) | fn test_extract_token_from_query_success() {
  function test_extract_token_from_query_special_chars (line 455) | fn test_extract_token_from_query_special_chars() {
  function test_extract_token_from_query_missing_param (line 468) | fn test_extract_token_from_query_missing_param() {
  function test_extract_token_from_query_invalid_uri (line 484) | fn test_extract_token_from_query_invalid_uri() {
  function test_get_jwt_locations_default (line 496) | fn test_get_jwt_locations_default() {
  function test_get_jwt_locations_single_bearer (line 509) | fn test_get_jwt_locations_single_bearer() {
  function test_get_jwt_locations_single_cookie (line 524) | fn test_get_jwt_locations_single_cookie() {
  function test_get_jwt_locations_single_query (line 541) | fn test_get_jwt_locations_single_query() {
  function test_get_jwt_locations_multiple (line 558) | fn test_get_jwt_locations_multiple() {
  function test_extract_token_from_location_bearer (line 581) | fn test_extract_token_from_location_bearer() {
  function test_extract_token_from_location_cookie (line 596) | fn test_extract_token_from_location_cookie() {
  function test_extract_token_from_location_query (line 616) | fn test_extract_token_from_location_query() {
  function test_extract_token_single_location_success (line 636) | fn test_extract_token_single_location_success() {
  function test_extract_token_multiple_locations_fallback (line 658) | fn test_extract_token_multiple_locations_fallback() {
  function test_extract_token_all_locations_fail (line 684) | fn test_extract_token_all_locations_fail() {
  function test_extract_from_default (line 713) | fn test_extract_from_default() {
  function test_extract_from_bearer (line 734) | fn test_extract_from_bearer() {
  function test_extract_from_cookie (line 757) | fn test_extract_from_cookie() {
  function test_extract_from_query (line 782) | fn test_extract_from_query() {
  function test_extract_from_multiple_locations (line 807) | fn test_extract_from_multiple_locations() {
  function test_extract_token_error_message_for_missing_token (line 835) | fn test_extract_token_error_message_for_missing_token() {

FILE: src/controller/extractor/shared_store.rs
  type SharedStore (line 6) | pub struct SharedStore<T>(pub T);
  type Rejection (line 12) | type Rejection = Error;
  function from_request_parts (line 14) | async fn from_request_parts(

FILE: src/controller/extractor/validate.rs
  type JsonValidateWithMessage (line 41) | pub struct JsonValidateWithMessage<T>(pub T);
  type Rejection (line 48) | type Rejection = Error;
  function from_request (line 50) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
  type FormValidateWithMessage (line 86) | pub struct FormValidateWithMessage<T>(pub T);
  type Rejection (line 93) | type Rejection = Error;
  function from_request (line 95) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
  type JsonValidate (line 132) | pub struct JsonValidate<T>(pub T);
  type Rejection (line 139) | type Rejection = Error;
  function from_request (line 141) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
  type FormValidate (line 180) | pub struct FormValidate<T>(pub T);
  type Rejection (line 187) | type Rejection = Error;
  function from_request (line 189) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
  type QueryValidateWithMessage (line 228) | pub struct QueryValidateWithMessage<T>(pub T);
  type Rejection (line 235) | type Rejection = Error;
  function from_request (line 237) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
  type QueryValidate (line 276) | pub struct QueryValidate<T>(pub T);
  type Rejection (line 283) | type Rejection = Error;
  function from_request (line 285) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
  type TestUser (line 312) | struct TestUser {
  type TestQueryParams (line 320) | struct TestQueryParams {
  function create_json_request (line 327) | fn create_json_request(json: &str) -> HttpRequest<Body> {
  function create_form_request (line 336) | fn create_form_request(form_data: &str) -> HttpRequest<Body> {
  function create_query_request (line 348) | fn create_query_request(query: &str) -> HttpRequest<Body> {
  function assert_response_status_and_body (line 356) | async fn assert_response_status_and_body(
  function test_json_validate_with_message_valid (line 377) | async fn test_json_validate_with_message_valid() {
  function test_json_validate_with_message_invalid (line 390) | async fn test_json_validate_with_message_invalid() {
  function test_form_validate_with_message_valid (line 426) | async fn test_form_validate_with_message_valid() {
  function test_form_validate_with_message_invalid (line 439) | async fn test_form_validate_with_message_invalid() {
  function test_json_validate_valid (line 475) | async fn test_json_validate_valid() {
  function test_json_validate_invalid (line 488) | async fn test_json_validate_invalid() {
  function test_form_validate_valid (line 511) | async fn test_form_validate_valid() {
  function test_form_validate_invalid (line 524) | async fn test_form_validate_invalid() {
  function test_malformed_json (line 547) | async fn test_malformed_json() {
  function test_malformed_form (line 564) | async fn test_malformed_form() {
  type CustomData (line 586) | struct CustomData {
  method validate (line 592) | fn validate(&self) -> Result<(), ModelValidationErrors> {
  function test_json_validate_with_message_custom_validator_invalid (line 624) | async fn test_json_validate_with_message_custom_validator_invalid() {
  function test_json_validate_with_message_custom_validator_valid (line 644) | async fn test_json_validate_with_message_custom_validator_valid() {
  function test_query_validate_with_message_valid (line 653) | async fn test_query_validate_with_message_valid() {
  function test_query_validate_with_message_invalid (line 666) | async fn test_query_validate_with_message_invalid() {
  function test_query_validate_valid (line 702) | async fn test_query_validate_valid() {
  function test_query_validate_invalid (line 715) | async fn test_query_validate_invalid() {
  function test_malformed_query (line 738) | async fn test_malformed_query() {

FILE: src/controller/format.rs
  function empty (line 60) | pub fn empty() -> Result<Response> {
  function text (line 81) | pub fn text(t: &str) -> Result<Response> {
  function json (line 110) | pub fn json<T: Serialize>(t: T) -> Result<Response> {
  function empty_json (line 119) | pub fn empty_json() -> Result<Response> {
  function html (line 139) | pub fn html(content: &str) -> Result<Response> {
  function yaml (line 159) | pub fn yaml(content: &str) -> Result<Response> {
  function redirect (line 182) | pub fn redirect(to: &str) -> Result<Response> {
  function view (line 191) | pub fn view<V, S>(v: &V, key: &str, data: S) -> Result<Response>
  function template (line 205) | pub fn template<S>(template: &str, data: S) -> Result<Response>
  type RenderBuilder (line 213) | pub struct RenderBuilder {
    method new (line 219) | pub fn new() -> Self {
    method response (line 227) | pub fn response(self) -> Builder {
    method status (line 233) | pub fn status<T>(self, status: T) -> Self
    method header (line 245) | pub fn header<K, V>(self, key: K, value: V) -> Self
    method etag (line 263) | pub fn etag(self, etag: &str) -> Result<Self> {
    method cookies (line 275) | pub fn cookies(self, cookies: &[Cookie<'_>]) -> Result<Self> {
    method text (line 289) | pub fn text(self, content: &str) -> Result<Response> {
    method empty (line 304) | pub fn empty(self) -> Result<Response> {
    method view (line 313) | pub fn view<V, S>(self, v: &V, key: &str, data: S) -> Result<Response>
    method template (line 327) | pub fn template<S>(self, template: &str, data: S) -> Result<Response>
    method html (line 339) | pub fn html(self, content: &str) -> Result<Response> {
    method json (line 354) | pub fn json<T>(self, item: T) -> Result<Response>
    method redirect (line 375) | pub fn redirect(self, to: &str) -> Result<Response> {
    method redirect_with_header_key (line 385) | pub fn redirect_with_header_key<K>(self, key: K, to: &str) -> Result<R...
  method default (line 399) | fn default() -> Self {
  function render (line 405) | pub fn render() -> RenderBuilder {
  function response_body_to_string (line 418) | async fn response_body_to_string(response: Response<Body>) -> String {
  function get_header_from_response (line 425) | pub fn get_header_from_response(response: &Response<Body>, header: &str)...
  function empty_response_format (line 430) | async fn empty_response_format() {
  function text_response_format (line 438) | async fn text_response_format() {
  function json_response_format (line 447) | async fn json_response_format() {
  function empty_json_response_format (line 459) | async fn empty_json_response_format() {
  function html_response_format (line 470) | async fn html_response_format() {
  function yaml_response_format (line 479) | async fn yaml_response_format() {
  function redirect_response (line 488) | async fn redirect_response() {
  function view_response (line 497) | async fn view_response() {
  function template_response (line 513) | async fn template_response() {
  function builder_set_status_code_response (line 521) | async fn builder_set_status_code_response() {
  function builder_set_headers_response (line 527) | async fn builder_set_headers_response() {
  function builder_etag_response (line 547) | async fn builder_etag_response() {
  function builder_cookies_response (line 559) | async fn builder_cookies_response() {
  function builder_text_response (line 573) | async fn builder_text_response() {
  function builder_empty_response (line 581) | async fn builder_empty_response() {
  function builder_view_response (line 590) | async fn builder_view_response() {
  function builder_template_response (line 608) | async fn builder_template_response() {
  function builder_html_response (line 618) | async fn builder_html_response() {
  function builder_json_response (line 627) | async fn builder_json_response() {
  function builder_redirect_response (line 639) | async fn builder_redirect_response() {
  function builder_redirect_with_custom_header_response (line 647) | async fn builder_redirect_with_custom_header_response() {

FILE: src/controller/middleware/_archive/content_etag.rs
  type EtagLayer (line 18) | pub struct EtagLayer;
    method new (line 21) | pub fn new() -> Self {
    type Service (line 26) | type Service = EtagMiddleware<S>;
    method layer (line 28) | fn layer(&self, inner: S) -> Self::Service {
  type EtagMiddleware (line 34) | pub struct EtagMiddleware<S> {
  type Response (line 45) | type Response = S::Response;
  type Error (line 46) | type Error = BoxError;
  type Future (line 47) | type Future =
  function poll_ready (line 50) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
  function call (line 54) | fn call(&mut self, request: Request) -> Self::Future {
  function calculate_etag (line 99) | fn calculate_etag(bytes: &Bytes) -> String {

FILE: src/controller/middleware/catch_panic.rs
  type CatchPanic (line 19) | pub struct CatchPanic {
  function handle_panic (line 29) | fn handle_panic(err: Box<dyn std::any::Any + Send + 'static>) -> axum::r...
  method name (line 42) | fn name(&self) -> &'static str {
  method is_enabled (line 47) | fn is_enabled(&self) -> bool {
  method config (line 51) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 56) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...
  function panic_enabled (line 77) | async fn panic_enabled() {
  function should_be_disabled (line 98) | fn should_be_disabled() {

FILE: src/controller/middleware/compression.rs
  type Compression (line 15) | pub struct Compression {
  method name (line 22) | fn name(&self) -> &'static str {
  method is_enabled (line 27) | fn is_enabled(&self) -> bool {
  method config (line 31) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 36) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...

FILE: src/controller/middleware/cors.rs
  type Cors (line 19) | pub struct Cors {
    method cors (line 90) | pub fn cors(&self) -> Result<cors::CorsLayer> {
  function default_allow_origins (line 44) | fn default_allow_origins() -> Vec<String> {
  function default_allow_headers (line 48) | fn default_allow_headers() -> Vec<String> {
  function default_allow_methods (line 52) | fn default_allow_methods() -> Vec<String> {
  function default_expose_headers (line 56) | fn default_expose_headers() -> Vec<String> {
  function default_vary_headers (line 60) | fn default_vary_headers() -> Vec<String> {
  method default (line 69) | fn default() -> Self {
  method name (line 163) | fn name(&self) -> &'static str {
  method is_enabled (line 168) | fn is_enabled(&self) -> bool {
  method config (line 172) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 177) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...
  function cors_enabled (line 205) | async fn cors_enabled(
  function cors_options (line 264) | async fn cors_options() {
  function should_be_disabled (line 312) | fn should_be_disabled() {

FILE: src/controller/middleware/etag.rs
  type Etag (line 28) | pub struct Etag {
  method name (line 35) | fn name(&self) -> &'static str {
  method is_enabled (line 40) | fn is_enabled(&self) -> bool {
  method config (line 44) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 49) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...
  type EtagLayer (line 57) | struct EtagLayer;
    type Service (line 60) | type Service = EtagMiddleware<S>;
    method layer (line 62) | fn layer(&self, inner: S) -> Self::Service {
  type EtagMiddleware (line 68) | struct EtagMiddleware<S> {
  type Response (line 77) | type Response = S::Response;
  type Error (line 78) | type Error = S::Error;
  type Future (line 80) | type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
  function poll_ready (line 82) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
  function call (line 86) | fn call(&mut self, request: Request) -> Self::Future {

FILE: src/controller/middleware/fallback.rs
  type StatusCodeWrapper (line 15) | pub struct StatusCodeWrapper(pub StatusCode);
  type Fallback (line 18) | pub struct Fallback {
  function default_status_code (line 39) | fn default_status_code() -> StatusCode {
  method default (line 44) | fn default() -> Self {
  function deserialize_status_code (line 49) | fn deserialize_status_code<'de, D>(de: D) -> Result<StatusCode, D::Error>
  function serialize_status_code (line 66) | fn serialize_status_code<S>(status: &StatusCode, ser: S) -> Result<S::Ok...
  method name (line 74) | fn name(&self) -> &'static str {
  method is_enabled (line 79) | fn is_enabled(&self) -> bool {
  method config (line 83) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 88) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...

FILE: src/controller/middleware/format.rs
  type Format (line 14) | pub struct Format(pub RespondTo);
    type Rejection (line 55) | type Rejection = Error;
    method from_request_parts (line 57) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<S...
  type RespondTo (line 17) | pub enum RespondTo {
    type Rejection (line 66) | type Rejection = Error;
    method from_request_parts (line 68) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<S...
  function detect_format (line 25) | fn detect_format(content_type: &str) -> RespondTo {
  function get_respond_to (line 40) | pub fn get_respond_to(headers: &HeaderMap) -> RespondTo {

FILE: src/controller/middleware/limit_payload.rs
  type DefaultBodyLimitKind (line 20) | pub enum DefaultBodyLimitKind {
  type LimitPayload (line 26) | pub struct LimitPayload {
  method default (line 35) | fn default() -> Self {
  function default_body_limit (line 43) | fn default_body_limit() -> DefaultBodyLimitKind {
  function deserialize_body_limit (line 47) | fn deserialize_body_limit<'de, D>(deserializer: D) -> Result<DefaultBody...
  method name (line 65) | fn name(&self) -> &'static str {
  method is_enabled (line 70) | fn is_enabled(&self) -> bool {
  method config (line 74) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 80) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...

FILE: src/controller/middleware/logger.rs
  type Config (line 22) | pub struct Config {
  type Middleware (line 29) | pub struct Middleware {
  function new (line 37) | pub fn new(config: &Config, environment: &Environment) -> Middleware {
  method name (line 46) | fn name(&self) -> &'static str {
  method is_enabled (line 51) | fn is_enabled(&self) -> bool {
  method config (line 55) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 69) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...

FILE: src/controller/middleware/mod.rs
  type MiddlewareLayer (line 46) | pub trait MiddlewareLayer {
    method name (line 50) | fn name(&self) -> &'static str;
    method is_enabled (line 55) | fn is_enabled(&self) -> bool {
    method config (line 63) | fn config(&self) -> serde_json::Result<serde_json::Value>;
    method apply (line 71) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppConte...
  function default_middleware_stack (line 76) | pub fn default_middleware_stack(ctx: &AppContext) -> Vec<Box<dyn Middlew...
  type Config (line 175) | pub struct Config {

FILE: src/controller/middleware/powered_by.rs
  function get_default_ident_header_value (line 21) | fn get_default_ident_header_value() -> &'static HeaderValue {
  type Middleware (line 28) | pub struct Middleware {
  function new (line 35) | pub fn new(ident: Option<&str>) -> Middleware {
  method name (line 62) | fn name(&self) -> &'static str {
  method is_enabled (line 67) | fn is_enabled(&self) -> bool {
  method config (line 71) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 80) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...

FILE: src/controller/middleware/remote_ip.rs
  function get_local_trusted_proxies (line 37) | fn get_local_trusted_proxies() -> &'static Vec<IpNetwork> {
  constant X_FORWARDED_FOR (line 53) | const X_FORWARDED_FOR: &str = "X-Forwarded-For";
  type RemoteIpMiddleware (line 96) | pub struct RemoteIpMiddleware {
  method name (line 106) | fn name(&self) -> &'static str {
  method is_enabled (line 111) | fn is_enabled(&self) -> bool {
  method config (line 117) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 122) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...
  function maybe_get_forwarded (line 128) | fn maybe_get_forwarded(
  type RemoteIP (line 181) | pub enum RemoteIP {
    type Rejection (line 191) | type Rejection = ();
    method from_request_parts (line 193) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<S...
    method fmt (line 200) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  type RemoteIPLayer (line 210) | struct RemoteIPLayer {
    method new (line 219) | pub fn new(config: &RemoteIpMiddleware) -> Result<Self> {
    type Service (line 243) | type Service = RemoteIPMiddleware<S>;
    method layer (line 245) | fn layer(&self, inner: S) -> Self::Service {
  type RemoteIPMiddleware (line 256) | pub struct RemoteIPMiddleware<S> {
  type Response (line 266) | type Response = S::Response;
  type Error (line 267) | type Error = S::Error;
  type Future (line 268) | type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
  function poll_ready (line 270) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
  function call (line 274) | fn call(&mut self, mut req: Request<Body>) -> Self::Future {
  function xff (line 313) | fn xff(val: &str) -> HeaderMap {
  function test_parsing (line 324) | pub fn test_parsing() {

FILE: src/controller/middleware/request_id.rs
  constant X_REQUEST_ID (line 18) | const X_REQUEST_ID: &str = "x-request-id";
  constant MAX_LEN (line 19) | const MAX_LEN: usize = 255;
  function get_id_cleanup (line 25) | fn get_id_cleanup() -> &'static Regex {
  type RequestId (line 29) | pub struct RequestId {
  method name (line 36) | fn name(&self) -> &'static str {
  method is_enabled (line 41) | fn is_enabled(&self) -> bool {
  method config (line 45) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 57) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...
  type LocoRequestId (line 64) | pub struct LocoRequestId(String);
    method get (line 69) | pub fn get(&self) -> &str {
  function request_id_middleware (line 80) | pub async fn request_id_middleware(mut request: Request, next: Next) -> ...
  function make_request_id (line 97) | fn make_request_id(maybe_request_id: Option<HeaderValue>) -> String {
  function create_or_fetch_request_id (line 121) | fn create_or_fetch_request_id() {

FILE: src/controller/middleware/secure_headers.rs
  function get_presets (line 26) | fn get_presets() -> &'static HashMap<String, BTreeMap<String, String>> {
  type SecureHeader (line 79) | pub struct SecureHeader {
    method as_headers (line 123) | fn as_headers(&self) -> Result<Vec<(HeaderName, HeaderValue)>> {
  method default (line 89) | fn default() -> Self {
  function default_preset (line 94) | fn default_preset() -> String {
  method name (line 100) | fn name(&self) -> &'static str {
  method is_enabled (line 105) | fn is_enabled(&self) -> bool {
  method config (line 109) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 114) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...
  type SecureHeaders (line 158) | pub struct SecureHeaders {
    method new (line 168) | pub fn new(config: &SecureHeader) -> Result<Self> {
    type Service (line 176) | type Service = SecureHeadersMiddleware<S>;
    method layer (line 179) | fn layer(&self, inner: S) -> Self::Service {
  type SecureHeadersMiddleware (line 190) | pub struct SecureHeadersMiddleware<S> {
  type Response (line 200) | type Response = S::Response;
  type Error (line 201) | type Error = S::Error;
  type Future (line 202) | type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
  function poll_ready (line 204) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
  function call (line 208) | fn call(&mut self, request: Request<Body>) -> Self::Future {
  function normalize_headers (line 238) | fn normalize_headers(headers: &HeaderMap) -> BTreeMap<String, String> {
  function can_set_headers (line 249) | async fn can_set_headers() {
  function can_override_headers (line 269) | async fn can_override_headers() {
  function can_dynamically_override_headers (line 293) | async fn can_dynamically_override_headers() {
  function default_is_github_preset (line 331) | async fn default_is_github_preset() {

FILE: src/controller/middleware/static_assets.rs
  type StaticAssets (line 25) | pub struct StaticAssets {
  method default (line 46) | fn default() -> Self {
  function default_must_exist (line 51) | fn default_must_exist() -> bool {
  function default_precompressed (line 55) | fn default_precompressed() -> bool {
  function default_fallback (line 59) | fn default_fallback() -> PathBuf {
  function default_folder_config (line 63) | fn default_folder_config() -> FolderConfig {
  type FolderConfig (line 71) | pub struct FolderConfig {
  method name (line 81) | fn name(&self) -> &'static str {
  method is_enabled (line 86) | fn is_enabled(&self) -> bool {
  method config (line 90) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 103) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...

FILE: src/controller/middleware/static_assets_embedded.rs
  type StaticAssets (line 30) | pub struct StaticAssets {
  method default (line 49) | fn default() -> Self {
  function default_must_exist (line 54) | fn default_must_exist() -> bool {
  function default_precompressed (line 58) | fn default_precompressed() -> bool {
  function default_fallback (line 62) | fn default_fallback() -> PathBuf {
  function default_folder_config (line 66) | fn default_folder_config() -> FolderConfig {
  type FolderConfig (line 74) | pub struct FolderConfig {
  type EmbeddedAssets (line 82) | pub struct EmbeddedAssets {
    method new (line 87) | fn new(fallback_path: &str) -> Self {
    method serve (line 122) | fn serve(&self, uri: &str) -> impl IntoResponse {
  method name (line 167) | fn name(&self) -> &'static str {
  method is_enabled (line 172) | fn is_enabled(&self) -> bool {
  method config (line 176) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 184) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...

FILE: src/controller/middleware/timeout.rs
  type TimeOut (line 24) | pub struct TimeOut {
  method default (line 33) | fn default() -> Self {
  function default_timeout (line 38) | fn default_timeout() -> u64 {
  method name (line 44) | fn name(&self) -> &'static str {
  method is_enabled (line 49) | fn is_enabled(&self) -> bool {
  method config (line 53) | fn config(&self) -> serde_json::Result<serde_json::Value> {
  method apply (line 62) | fn apply(&self, app: AXRouter<AppContext>) -> Result<AXRouter<AppContext...

FILE: src/controller/mod.rs
  function unauthorized (line 112) | pub fn unauthorized<T: Into<String>, U>(msg: T) -> Result<U> {
  function bad_request (line 121) | pub fn bad_request<T: Into<String>, U>(msg: T) -> Result<U> {
  function not_found (line 130) | pub fn not_found<T>() -> Result<T> {
  type ErrorDetail (line 135) | pub struct ErrorDetail {
    method new (line 147) | pub fn new<T1: Into<String> + AsRef<str>, T2: Into<String> + AsRef<str>>(
    method with_reason (line 161) | pub fn with_reason<T: Into<String>>(error: T) -> Self {
  type Json (line 172) | pub struct Json<T>(pub T);
  method into_response (line 175) | fn into_response(self) -> axum::response::Response {
  method into_response (line 183) | fn into_response(self) -> Response {

FILE: src/controller/monitoring.rs
  type Health (line 19) | pub struct Health {
  function ping (line 27) | pub async fn ping() -> Result<Response> {
  function health (line 35) | pub async fn health() -> Result<Response> {
  function readiness (line 44) | pub async fn readiness(State(ctx): State<AppContext>) -> (StatusCode, Re...
  function routes (line 101) | pub fn routes() -> Routes {
  function ping_works (line 120) | async fn ping_works() {
  function health_works (line 148) | async fn health_works() {
  function readiness_no_features (line 177) | async fn readiness_no_features() {
  function readiness_with_db_success (line 206) | async fn readiness_with_db_success() {
  function readiness_with_db_failure (line 235) | async fn readiness_with_db_failure() {
  function readiness_with_cache_inmem (line 265) | async fn readiness_with_cache_inmem() {
  function readiness_with_cache_redis_success (line 299) | async fn readiness_with_cache_redis_success() {
  function readiness_with_cache_redis_failure (line 338) | async fn readiness_with_cache_redis_failure() {
  function readiness_with_queue_not_present (line 380) | async fn readiness_with_queue_not_present() {
  function readiness_with_queue_present_failure (line 412) | async fn readiness_with_queue_present_failure() {

FILE: src/controller/routes.rs
  type Routes (line 9) | pub struct Routes {
    method new (line 25) | pub fn new() -> Self {
    method at (line 53) | pub fn at(prefix: &str) -> Self {
    method add (line 81) | pub fn add(mut self, uri: &str, method: axum::routing::MethodRouter<Ap...
    method merge (line 147) | pub fn merge(mut self, other: Self) -> Self {
    method merge_all (line 197) | pub fn merge_all(mut self, others: Vec<Self>) -> Self {
    method prefix (line 228) | pub fn prefix(mut self, uri: &str) -> Self {
    method layer (line 251) | pub fn layer<L>(self, layer: L) -> Self
    method nest (line 328) | pub fn nest(mut self, path: &str, nested_routes: Self) -> Self {
  type Handler (line 16) | pub struct Handler {
  function users (line 367) | async fn users() -> Result<Response> {
  function user_detail (line 371) | async fn user_detail() -> Result<Response> {
  function ping (line 375) | async fn ping() -> Result<Response> {
  function test_nest_method (line 380) | fn test_nest_method() {
  function test_nest_method_with_root_path (line 407) | fn test_nest_method_with_root_path() {
  function test_nest_method_with_trailing_slash (line 428) | fn test_nest_method_with_trailing_slash() {
  function test_nest_method_without_leading_slash (line 443) | fn test_nest_method_without_leading_slash() {
  function test_merge_method (line 458) | fn test_merge_method() {
  function test_merge_and_nest_combination (line 490) | fn test_merge_and_nest_combination() {
  function test_merge_all_method (line 530) | fn test_merge_all_method() {
  function test_merge_all_and_nest_combination (line 555) | fn test_merge_all_and_nest_combination() {

FILE: src/controller/views/engine.rs
  type HotReloadingTeraEngine (line 16) | pub struct HotReloadingTeraEngine {
  type TeraView (line 25) | pub struct TeraView(
    method build (line 36) | pub fn build() -> Result<Self> {
    method build_with_post_process (line 49) | pub fn build_with_post_process(
    method create_tera_instance (line 63) | fn create_tera_instance<P: AsRef<Path>>(path: P) -> Result<tera::Tera> {
    method from_custom_dir (line 83) | pub fn from_custom_dir<P: AsRef<Path>>(
  method render (line 177) | fn render<S: Serialize>(&self, key: &str, data: S) -> Result<String> {
  function can_render_view (line 214) | fn can_render_view() {
  function template_inheritance_hot_reload (line 238) | fn template_inheritance_hot_reload() {

FILE: src/controller/views/engine_embedded.rs
  type TeraView (line 15) | pub struct TeraView {
    method build (line 26) | pub fn build() -> Result<Self> {
    method post_process (line 37) | pub fn post_process(
    method from_embedded_templates (line 52) | pub fn from_embedded_templates() -> Result<Self> {
    method load_templates_into_tera (line 72) | fn load_templates_into_tera(tera: &mut tera::Tera) -> Result<()> {
    method log_template_info (line 80) | fn log_template_info(templates: &BTreeMap<String, &'static str>) {
    method add_templates_to_tera (line 90) | fn add_templates_to_tera(
  method render (line 114) | fn render<S: Serialize>(&self, key: &str, data: S) -> Result<String> {

FILE: src/controller/views/mod.rs
  type ViewRenderer (line 20) | pub trait ViewRenderer {
    method render (line 26) | fn render<S: Serialize>(&self, key: &str, data: S) -> Result<String>;
  type ViewEngine (line 30) | pub struct ViewEngine<E>(pub E);
  function new (line 34) | pub fn new(engine: E) -> Self {
  function template (line 55) | pub fn template<S>(template: &str, data: S) -> Result<String>
  function from (line 64) | fn from(inner: E) -> Self {
  type Rejection (line 74) | type Rejection = std::convert::Infallible;
  function from_request_parts (line 76) | async fn from_request_parts(

FILE: src/controller/views/pagination.rs
  type Pager (line 4) | pub struct Pager<T> {
  type PagerMeta (line 13) | pub struct PagerMeta {
  function new (line 26) | pub const fn new(results: T, meta: PagerMeta) -> Self {

FILE: src/controller/views/tera_builtins/filters/mod.rs
  function register_filters (line 3) | pub fn register_filters(tera: &mut tera::Tera) {

FILE: src/controller/views/tera_builtins/filters/number.rs
  function separate_with_commas (line 9) | fn separate_with_commas(num_str: &str) -> String {
  function separate_integer_part (line 20) | fn separate_integer_part(num_str: &str) -> String {
  function number_with_delimiter (line 54) | pub fn number_with_delimiter(value: &Value, _: &HashMap<String, Value>) ...
  function number_to_human_size (line 78) | pub fn number_to_human_size(value: &Value, _: &HashMap<String, Value>) -...
  function number_to_percentage (line 102) | pub fn number_to_percentage(value: &Value, options: &HashMap<String, Val...
  function test_number_with_delimiter (line 151) | fn test_number_with_delimiter(#[case] input: Value, #[case] expected: &s...
  function test_number_to_human_size (line 160) | fn test_number_to_human_size(#[case] input: Value, #[case] expected: &st...
  function test_number_to_percentage (line 169) | fn test_number_to_percentage(

FILE: src/data.rs
  constant DEFAULT_DATA_FOLDER (line 7) | const DEFAULT_DATA_FOLDER: &str = "data";
  function data_folder (line 8) | fn data_folder() -> String {
  function load_json_file_sync (line 17) | pub fn load_json_file_sync<T: DeserializeOwned>(path: &str) -> Result<T> {
  function load_json_file (line 30) | pub async fn load_json_file<T: DeserializeOwned>(path: &str) -> Result<T> {
  type TestData (line 47) | struct TestData {
  function test_load_json_file_sync_success (line 53) | fn test_load_json_file_sync_success() {
  function test_load_json_file_sync_file_not_found (line 78) | fn test_load_json_file_sync_file_not_found() {
  function test_load_json_file_sync_invalid_json (line 91) | fn test_load_json_file_sync_invalid_json() {
  function test_load_json_file_async_success (line 106) | async fn test_load_json_file_async_success() {
  function test_load_json_file_async_file_not_found (line 132) | async fn test_load_json_file_async_file_not_found() {
  function test_load_json_file_async_invalid_json (line 145) | async fn test_load_json_file_async_invalid_json() {

FILE: src/db.rs
  constant IGNORED_TABLES (line 33) | const IGNORED_TABLES: &[&str] = &[
  function re_extract_db_name (line 40) | fn re_extract_db_name() -> &'static Regex {
  type MultiDb (line 47) | pub struct MultiDb {
    method new (line 57) | pub async fn new(dbs_config: HashMap<String, config::Database>) -> App...
    method get (line 74) | pub fn get(&self, name: &str) -> AppResult<&DatabaseConnection> {
  function verify_access (line 87) | pub async fn verify_access(db: &DatabaseConnection) -> AppResult<()> {
  function converge (line 116) | pub async fn converge<H: Hooks, M: MigratorTrait>(
  function connect (line 145) | pub async fn connect(config: &config::Database) -> Result<DbConn, sea_or...
  function extract_db_name (line 198) | pub fn extract_db_name(conn_str: &str) -> AppResult<&str> {
  function create (line 210) | pub async fn create(db_uri: &str) -> AppResult<()> {
  function migrate (line 231) | pub async fn migrate<M: MigratorTrait>(db: &DatabaseConnection) -> Resul...
  function down (line 240) | pub async fn down<M: MigratorTrait>(
  function status (line 252) | pub async fn status<M: MigratorTrait>(db: &DatabaseConnection) -> Result...
  function reset (line 262) | pub async fn reset<M: MigratorTrait>(db: &DatabaseConnection) -> Result<...
  function seed (line 279) | pub async fn seed<A>(db: &DatabaseConnection, path: &str) -> crate::Resu...
  function has_id_column (line 326) | async fn has_id_column(
  function is_auto_increment (line 374) | async fn is_auto_increment(
  function reset_autoincrement (line 412) | pub async fn reset_autoincrement(
  type EntityCmd (line 462) | struct EntityCmd {
    method new (line 468) | fn new(config: &config::Database) -> Self {
    method merge_with_config (line 487) | fn merge_with_config(config: &config::Database, toml_config: &toml::Ta...
    method command (line 531) | fn command(&self) -> Vec<&str> {
  function entities (line 553) | pub async fn entities<M: MigratorTrait>(ctx: &AppContext) -> AppResult<S...
  function fix_entities (line 586) | fn fix_entities() -> AppResult<()> {
  function truncate_table (line 704) | pub async fn truncate_table<T>(db: &DatabaseConnection, _: T) -> Result<...
  function run_app_seed (line 717) | pub async fn run_app_seed<H: Hooks>(ctx: &AppContext, path: &Path) -> Ap...
  function create_postgres_database (line 724) | async fn create_postgres_database(
  function get_tables (line 766) | pub async fn get_tables(db: &DatabaseConnection) -> AppResult<Vec<String...
  function get_boolean_columns (line 814) | async fn get_boolean_columns(
  function dump_tables (line 871) | pub async fn dump_tables(
  function dump_schema (line 997) | pub async fn dump_schema(ctx: &AppContext, fname: &str) -> crate::Result...
  function test_sqlite_connect_success (line 1078) | async fn test_sqlite_connect_success() {
  function test_postgres_connect_success (line 1093) | async fn test_postgres_connect_success() {
  function test_sqlite_default_run_on_start (line 1113) | async fn test_sqlite_default_run_on_start() {
  function test_sqlite_custom_run_on_start (line 1141) | async fn test_sqlite_custom_run_on_start() {
  function test_postgres_run_on_start (line 1179) | async fn test_postgres_run_on_start() {
  function test_extract_db_name (line 1247) | fn test_extract_db_name(#[case] conn_str: &str, #[case] expected: &str) {
  function test_extract_db_name_failure (line 1265) | fn test_extract_db_name_failure(#[case] conn_str: &str) {
  function test_postgres_create_database (line 1275) | async fn test_postgres_create_database() {
  function test_postgres_has_id_column (line 1312) | async fn test_postgres_has_id_column() {
  function test_sqlite_has_id_column (line 1371) | async fn test_sqlite_has_id_column() {
  function test_postgres_is_auto_increment (line 1430) | async fn test_postgres_is_auto_increment() {
  function test_postgres_reset_autoincrement (line 1495) | async fn test_postgres_reset_autoincrement() {
  function test_sqlite_reset_autoincrement (line 1574) | async fn test_sqlite_reset_autoincrement() {
  type Model (line 1659) | pub struct Model {
  type Relation (line 1676) | pub enum Relation {}
  method def (line 1679) | fn def(&self) -> RelationDef {
  function sqlite_dump_tables_roundtrip (line 1688) | async fn sqlite_dump_tables_roundtrip() {
  function test_entity_cmd_new (line 1802) | fn test_entity_cmd_new() {
  function test_entity_cmd_merge_with_config (line 1812) | fn test_entity_cmd_merge_with_config() {

FILE: src/depcheck.rs
  type VersionStatus (line 9) | pub enum VersionStatus {
  type CrateStatus (line 19) | pub struct CrateStatus {
  type VersionCheckError (line 25) | pub enum VersionCheckError {
  type Result (line 33) | pub type Result<T> = std::result::Result<T, VersionCheckError>;
  function check_crate_versions (line 35) | pub fn check_crate_versions(
  function setup_test_dir (line 105) | fn setup_test_dir(cargo_lock_content: &str) -> Tree {
  function test_multiple_crates_mixed_results (line 113) | fn test_multiple_crates_mixed_results() {
  function test_invalid_version_format_in_cargo_lock (line 161) | fn test_invalid_version_format_in_cargo_lock() {
  function test_no_package_section_in_cargo_lock (line 182) | fn test_no_package_section_in_cargo_lock() {
  function test_exact_version_match_for_minimum_requirement (line 198) | fn test_exact_version_match_for_minimum_requirement() {
  function test_no_crates_in_min_versions_map (line 223) | fn test_no_crates_in_min_versions_map() {

FILE: src/doctor.rs
  constant SEAORM_INSTALLED (line 31) | const SEAORM_INSTALLED: &str = "SeaORM CLI is installed";
  constant SEAORM_NOT_INSTALLED (line 32) | const SEAORM_NOT_INSTALLED: &str = "SeaORM CLI was not found";
  constant SEAORM_NOT_FIX (line 33) | const SEAORM_NOT_FIX: &str = r"To fix, run:
  constant QUEUE_CONN_OK (line 35) | const QUEUE_CONN_OK: &str = "queue connection: success";
  constant QUEUE_CONN_FAILED (line 36) | const QUEUE_CONN_FAILED: &str = "queue connection: failed";
  constant QUEUE_NOT_CONFIGURED (line 37) | const QUEUE_NOT_CONFIGURED: &str = "queue not configured?";
  constant MIN_SEAORMCLI_VER (line 40) | const MIN_SEAORMCLI_VER: &str = "1.1.0";
  function get_re_crate_version (line 44) | fn get_re_crate_version() -> &'static Regex {
  function get_min_dep_versions (line 48) | fn get_min_dep_versions() -> &'static HashMap<&'static str, &'static str> {
  function check_cratesio_version (line 66) | pub fn check_cratesio_version(crate_name: &str, current_version: &str) -...
  type Resource (line 102) | pub enum Resource {
  type CheckStatus (line 113) | pub enum CheckStatus {
  type Check (line 121) | pub struct Check {
    method valid (line 132) | pub fn valid(&self) -> bool {
    method to_result (line 140) | pub fn to_result(&self) -> Result<()> {
    method fmt (line 154) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  function run_all (line 177) | pub async fn run_all<H: crate::app::Hooks>(
  function check_deps (line 223) | pub fn check_deps() -> Result<Check> {
  function check_db (line 262) | pub async fn check_db(config: &crate::config::Database) -> Check {
  function check_queue (line 294) | pub async fn check_queue(config: &Config) -> Check {
  function check_seaorm_cli (line 322) | pub fn check_seaorm_cli() -> Result<Check> {
  function check_published_loco_version (line 373) | pub fn check_published_loco_version() -> Result<Check> {

FILE: src/env_vars.rs
  constant POSTGRES_DB_OPTIONS (line 8) | pub const POSTGRES_DB_OPTIONS: &str = "LOCO_POSTGRES_DB_OPTIONS";
  constant LOCO_ENV (line 10) | pub const LOCO_ENV: &str = "LOCO_ENV";
  constant RAILS_ENV (line 12) | pub const RAILS_ENV: &str = "RAILS_ENV";
  constant NODE_ENV (line 14) | pub const NODE_ENV: &str = "NODE_ENV";
  constant CONFIG_FOLDER (line 16) | pub const CONFIG_FOLDER: &str = "LOCO_CONFIG_FOLDER";
  constant SCHEDULER_CONFIG (line 18) | pub const SCHEDULER_CONFIG: &str = "SCHEDULER_CONFIG";
  constant LOCO_DATA_FOLDER_ENV (line 20) | pub const LOCO_DATA_FOLDER_ENV: &str = "LOCO_DATA";
  function get (line 23) | pub fn get(key: &str) -> Result<String, std::env::VarError> {
  function get_or_default (line 29) | pub fn get_or_default(key: &str, default: &str) -> String {

FILE: src/environment.rs
  constant DEFAULT_ENVIRONMENT (line 21) | pub const DEFAULT_ENVIRONMENT: &str = "development";
  constant LOCO_ENV (line 22) | pub const LOCO_ENV: &str = "LOCO_ENV";
  constant RAILS_ENV (line 23) | pub const RAILS_ENV: &str = "RAILS_ENV";
  constant NODE_ENV (line 24) | pub const NODE_ENV: &str = "NODE_ENV";
  function resolve_from_env (line 33) | pub fn resolve_from_env() -> String {
  type Environment (line 42) | pub enum Environment {
    method from (line 27) | fn from(env: String) -> Self {
    method load (line 59) | pub fn load(&self) -> Result<Config> {
    method load_from_folder (line 72) | pub fn load_from_folder(&self, path: &Path) -> Result<Config> {
    method fmt (line 78) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Err (line 87) | type Err = &'static str;
  method from_str (line 89) | fn from_str(input: &str) -> std::result::Result<Self, Self::Err> {
  function test_resolve_env (line 105) | fn test_resolve_env() {
  function test_display (line 121) | fn test_display() {
  function test_into (line 127) | fn test_into() {

FILE: src/errors.rs
  type Error (line 31) | pub enum Error {
    method from (line 25) | fn from(val: serde_json::Error) -> Self {
    method wrap (line 165) | pub fn wrap(err: impl std::error::Error + Send + Sync + 'static) -> Se...
    method msg (line 169) | pub fn msg(err: impl std::error::Error + Send + Sync + 'static) -> Self {
    method string (line 173) | pub fn string(s: &str) -> Self {
    method bt (line 177) | pub fn bt(self) -> Self {

FILE: src/hash.rs
  function hash_password (line 21) | pub fn hash_password(pass: &str) -> Result<String> {
  function verify_password (line 48) | pub fn verify_password(pass: &str, hashed_password: &str) -> bool {
  function random_string (line 72) | pub fn random_string(length: usize) -> String {
  function can_hah_password (line 86) | fn can_hah_password() {
  function can_random_string (line 95) | fn can_random_string() {

FILE: src/initializers/extra_db.rs
  type ExtraDbInitializer (line 10) | pub struct ExtraDbInitializer;
  method name (line 14) | fn name(&self) -> String {
  method after_routes (line 18) | async fn after_routes(&self, router: AxumRouter, ctx: &AppContext) -> Re...

FILE: src/initializers/multi_db.rs
  type MultiDbInitializer (line 10) | pub struct MultiDbInitializer;
  method name (line 14) | fn name(&self) -> String {
  method after_routes (line 18) | async fn after_routes(&self, router: AxumRouter, ctx: &AppContext) -> Re...

FILE: src/lib.rs
  type Result (line 52) | pub type Result<T, E = Error> = std::result::Result<T, E>;

FILE: src/logger.rs
  type LogLevel (line 16) | pub enum LogLevel {
    method fmt (line 66) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  type Format (line 40) | pub enum Format {
  type Rotation (line 52) | pub enum Rotation {
  constant MODULE_WHITELIST (line 72) | const MODULE_WHITELIST: &[&str] = &[
  function init (line 104) | pub fn init<H: Hooks>(config: &config::Logger) -> Result<()> {
  function init_env_filter (line 181) | fn init_env_filter<H: Hooks>(override_filter: Option<&String>, level: &L...
  function init_layer (line 203) | fn init_layer<W2>(

FILE: src/mailer/email_sender.rs
  type EmailTransport (line 18) | pub enum EmailTransport {
  type EmailSender (line 28) | pub struct EmailSender {
    method smtp (line 46) | pub fn smtp(config: &config::SmtpMailer) -> Result<Self> {
    method stub (line 74) | pub fn stub() -> Self {
    method deliveries (line 82) | pub fn deliveries(&self) -> Deliveries {
    method mail (line 103) | pub async fn mail(&self, email: &Email) -> Result<()> {
  type Deliveries (line 34) | pub struct Deliveries {
  function can_send_email (line 169) | async fn can_send_email() {
  function can_send_email_with_custom_headers (line 205) | async fn can_send_email_with_custom_headers() {

FILE: src/mailer/mod.rs
  constant DEFAULT_FROM_SENDER (line 18) | pub const DEFAULT_FROM_SENDER: &str = "System <system@example.com>";
  type EmailHeaders (line 21) | pub struct EmailHeaders {
  type Args (line 30) | pub struct Args {
  type Email (line 42) | pub struct Email {
  type MailerOpts (line 66) | pub struct MailerOpts {
  type Mailer (line 74) | pub trait Mailer {
    method opts (line 77) | fn opts() -> MailerOpts {
    method mail (line 85) | async fn mail(ctx: &AppContext, email: &Email) -> Result<()> {
    method mail_template (line 98) | async fn mail_template(ctx: &AppContext, dir: &Dir<'_>, args: Args) ->...
  type MailerWorker (line 121) | pub struct MailerWorker {
    method queue (line 128) | fn queue() -> Option<String> {
    method build (line 132) | fn build(ctx: &AppContext) -> Self {
    method perform (line 138) | async fn perform(&self, email: Email) -> crate::Result<()> {

FILE: src/mailer/template.rs
  constant SUBJECT (line 22) | const SUBJECT: &str = "subject.t";
  constant HTML (line 24) | const HTML: &str = "html.t";
  constant TEXT (line 26) | const TEXT: &str = "text.t";
  function embedded_file (line 30) | fn embedded_file(dir: &Dir<'_>, name: &str) -> Result<String> {
  type Content (line 42) | pub struct Content {
  type Template (line 50) | pub struct Template<'a> {
  function new (line 57) | pub const fn new(dir: &'a Dir<'_>) -> Self {
  function render (line 63) | pub fn render(&self, locals: &serde_json::Value) -> Result<Content> {
  function can_render_template (line 89) | fn can_render_template() {

FILE: src/model/mod.rs
  type ModelError (line 13) | pub enum ModelError {
    method wrap (line 42) | pub fn wrap(err: impl std::error::Error + Send + Sync + 'static) -> Se...
    method to_msg (line 47) | pub fn to_msg(err: impl std::error::Error + Send + Sync + 'static) -> ...
    method msg (line 52) | pub fn msg(s: &str) -> Self {
  type ModelResult (line 38) | pub type ModelResult<T, E = ModelError> = std::result::Result<T, E>;
  type Authenticable (line 57) | pub trait Authenticable: Clone {
    method find_by_api_key (line 58) | async fn find_by_api_key(db: &DatabaseConnection, api_key: &str) -> Mo...
    method find_by_claims_key (line 59) | async fn find_by_claims_key(db: &DatabaseConnection, claims_key: &str)...

FILE: src/model/query/dsl/date_range.rs
  type DateRangeBuilder (line 7) | pub struct DateRangeBuilder<T: ColumnTrait> {
  function new (line 15) | pub const fn new(condition_builder: ConditionBuilder, col: T) -> Self {
  function dates (line 25) | pub fn dates(self, from: Option<&NaiveDateTime>, to: Option<&NaiveDateTi...
  function from (line 35) | pub fn from(self, from: &NaiveDateTime) -> Self {
  function to (line 45) | pub fn to(self, to: &NaiveDateTime) -> Self {
  function build (line 54) | pub fn build(self) -> ConditionBuilder {
  function condition_date_range_from (line 76) | fn condition_date_range_from() {
  function condition_date_range_to (line 101) | fn condition_date_range_to() {
  function condition_date_both (line 126) | fn condition_date_both() {

FILE: src/model/query/dsl/mod.rs
  type ConditionBuilder (line 12) | pub struct ConditionBuilder {
    method eq (line 235) | pub fn eq<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> S...
    method ne (line 260) | pub fn ne<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> S...
    method gt (line 285) | pub fn gt<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> S...
    method gte (line 311) | pub fn gte<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> ...
    method lt (line 337) | pub fn lt<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> S...
    method lte (line 363) | pub fn lte<T: ColumnTrait, V: Into<Value>>(self, col: T, value: V) -> ...
    method between (line 389) | pub fn between<T: ColumnTrait, V: Into<Value>>(self, col: T, a: V, b: ...
    method not_between (line 415) | pub fn not_between<T: ColumnTrait, V: Into<Value>>(self, col: T, a: V,...
    method like (line 441) | pub fn like<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -> Se...
    method not_like (line 467) | pub fn not_like<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -...
    method starts_with (line 493) | pub fn starts_with<T: ColumnTrait, V: Into<String>>(self, col: T, a: V...
    method ends_with (line 519) | pub fn ends_with<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) ...
    method contains (line 545) | pub fn contains<T: ColumnTrait, V: Into<String>>(self, col: T, a: V) -...
    method is_null (line 572) | pub fn is_null<T: ColumnTrait>(self, col: T) -> Self {
    method is_not_null (line 599) | pub fn is_not_null<T: ColumnTrait>(self, col: T) -> Self {
    method is_in (line 626) | pub fn is_in<T: ColumnTrait, V: Into<Value>, I: IntoIterator<Item = V>>(
    method is_not_in (line 657) | pub fn is_not_in<T: ColumnTrait, V: Into<Value>, I: IntoIterator<Item ...
    method date_range (line 696) | pub fn date_range<T: ColumnTrait>(self, col: T) -> date_range::DateRan...
    method build (line 701) | pub fn build(&self) -> Condition {
  type SortDirection (line 18) | pub enum SortDirection {
    method order (line 29) | pub const fn order(&self) -> Order {
  function condition (line 38) | pub fn condition() -> ConditionBuilder {
  function with (line 45) | pub const fn with(condition: Condition) -> ConditionBuilder {
  function eq (line 51) | pub fn eq<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> Condition...
  function not_equal (line 57) | pub fn not_equal<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> Co...
  function gt (line 63) | pub fn gt<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> Condition...
  function gt_equal (line 69) | pub fn gt_equal<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> Con...
  function lt (line 75) | pub fn lt<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> Condition...
  function lt_equal (line 81) | pub fn lt_equal<T: ColumnTrait, V: Into<Value>>(col: T, value: V) -> Con...
  function between (line 87) | pub fn between<T: ColumnTrait, V: Into<Value>>(col: T, a: V, b: V) -> Co...
  function not_between (line 93) | pub fn not_between<T: ColumnTrait, V: Into<Value>>(col: T, a: V, b: V) -...
  function like (line 99) | pub fn like<T: ColumnTrait, V: Into<String>>(col: T, a: V) -> ConditionB...
  function not_like (line 105) | pub fn not_like<T: ColumnTrait, V: Into<String>>(col: T, a: V) -> Condit...
  function starts_with (line 111) | pub fn starts_with<T: ColumnTrait, V: Into<String>>(col: T, a: V) -> Con...
  function ends_with (line 117) | pub fn ends_with<T: ColumnTrait, V: Into<String>>(col: T, a: V) -> Condi...
  function contains (line 123) | pub fn contains<T: ColumnTrait, V: Into<String>>(col: T, a: V) -> Condit...
  function is_null (line 130) | pub fn is_null<T: ColumnTrait>(col: T) -> ConditionBuilder {
  function is_not_null (line 137) | pub fn is_not_null<T: ColumnTrait>(col: T) -> ConditionBuilder {
  function is_in (line 144) | pub fn is_in<T: ColumnTrait, V: Into<Value>, I: IntoIterator<Item = V>>(
  function is_not_in (line 154) | pub fn is_not_in<T: ColumnTrait, V: Into<Value>, I: IntoIterator<Item = ...
  function date_range (line 163) | pub fn date_range<T: ColumnTrait>(col: T) -> date_range::DateRangeBuilde...
  method into_condition (line 168) | fn into_condition(self) -> Condition {
  function condition_eq (line 715) | fn condition_eq() {
  function condition_ne (line 730) | fn condition_ne() {
  function condition_gt (line 745) | fn condition_gt() {
  function condition_gte (line 760) | fn condition_gte() {
  function condition_lt (line 775) | fn condition_lt() {
  function condition_lte (line 790) | fn condition_lte() {
  function condition_between (line 805) | fn condition_between() {
  function condition_not_between (line 820) | fn condition_not_between() {
  function condition_like (line 835) | fn condition_like() {
  function condition_not_like (line 850) | fn condition_not_like() {
  function condition_starts_with (line 865) | fn condition_starts_with() {
  function condition_ends_with (line 880) | fn condition_ends_with() {
  function condition_contains (line 895) | fn condition_contains() {
  function condition_is_null (line 910) | fn condition_is_null() {
  function condition_is_not_null (line 925) | fn condition_is_not_null() {
  function condition_is_in (line 940) | fn condition_is_in() {
  function condition_is_not_in (line 955) | fn condition_is_not_in() {

FILE: src/model/query/paginate/mod.rs
  function default_page_size (line 5) | const fn default_page_size() -> u64 {
  function default_page (line 10) | const fn default_page() -> u64 {
  type PaginationQuery (line 32) | pub struct PaginationQuery {
    method page (line 49) | pub fn page(page: u64) -> Self {
  method default (line 59) | fn default() -> Self {
  function deserialize_pagination_filter (line 69) | fn deserialize_pagination_filter<'de, D>(deserializer: D) -> Result<u64,...
  type PageResponse (line 78) | pub struct PageResponse<T> {
  function paginate (line 145) | pub async fn paginate<E>(
  function fetch_page (line 199) | pub async fn fetch_page<'db, C, S>(

FILE: src/scheduler.rs
  function get_re_is_cron_syntax (line 21) | fn get_re_is_cron_syntax() -> &'static Regex {
  type Error (line 27) | pub enum Error {
  type Result (line 51) | pub type Result<T, E = Error> = std::result::Result<T, E>;
  type Config (line 56) | pub struct Config {
  type Job (line 67) | pub struct Job {
    method prepare_command (line 161) | pub fn prepare_command(
  type Scheduler (line 121) | pub struct Scheduler {
    method fmt (line 89) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    method from_config (line 214) | pub fn from_config<H: Hooks>(config: &Path, environment: &Environment)...
    method new (line 235) | pub fn new<H: Hooks>(data: &Config, environment: &Environment) -> Resu...
    method by_spec (line 267) | pub fn by_spec(self, include_jobs: &Spec) -> Self {
    method run (line 294) | pub async fn run(self) -> Result<()> {
  type Spec (line 130) | pub struct Spec {
  type Output (line 137) | pub enum Output {
  type JobDescription (line 149) | pub struct JobDescription {
    method run (line 195) | pub fn run(&self) -> io::Result<std::process::Output> {
  function execute_job (line 353) | fn execute_job(job_name: &str, uuid: Uuid, job_description: &JobDescript...
  function setup_scheduler_config (line 391) | fn setup_scheduler_config() -> (Scheduler, tree_fs::Tree) {
  function can_display_scheduler (line 434) | pub fn can_display_scheduler() {
  function can_load_from_config_local_config (line 440) | pub fn can_load_from_config_local_config() {
  function can_load_from_env_config (line 447) | pub async fn can_load_from_env_config() {
  function can_load_jobs_by_spec_tag_multiple_jobs (line 458) | pub fn can_load_jobs_by_spec_tag_multiple_jobs() {
  function can_load_jobs_by_spec_tag_single_jobs (line 469) | pub fn can_load_jobs_by_spec_tag_single_jobs() {
  function can_load_jobs_by_spec_with_job_name (line 481) | pub fn can_load_jobs_by_spec_with_job_name() {
  function can_prepare_command (line 495) | pub fn can_prepare_command(#[case] test_name: &str, #[case] run: &str, #...
  function can_run (line 517) | pub async fn can_run() {

FILE: src/schema.rs
  type GeneralIds (line 13) | enum GeneralIds {
  function alter (line 19) | pub fn alter<T: IntoIden + 'static>(name: T) -> TableAlterStatement {
  function table_auto_tz (line 24) | pub fn table_auto_tz<T>(name: T) -> TableCreateStatement
  function timestamps_tz (line 34) | pub fn timestamps_tz(t: TableCreateStatement) -> TableCreateStatement {
  function timestamptz_null (line 42) | pub fn timestamptz_null<T>(name: T) -> ColumnDef
  function timestamptz (line 53) | pub fn timestamptz<T>(name: T) -> ColumnDef
  function enum_type (line 64) | pub fn enum_type<T>(name: T, enum_name: &str) -> ColumnDef
  function enum_type_null (line 75) | pub fn enum_type_null<T>(name: T, enum_name: &str) -> ColumnDef
  function enum_type_with_default (line 93) | pub fn enum_type_with_default<T>(name: T, enum_name: &str, default_value...
  function enum_type_null_with_default (line 112) | pub fn enum_type_null_with_default<T>(name: T, enum_name: &str, default_...
  function check_enum_exists (line 124) | async fn check_enum_exists(m: &SchemaManager<'_>, enum_name: &str) -> Re...
  type ColType (line 158) | pub enum ColType {
    method array (line 294) | pub fn array(kind: ArrayColType) -> Self {
    method array_uniq (line 300) | pub fn array_uniq(kind: ArrayColType) -> Self {
    method array_null (line 306) | pub fn array_null(kind: ArrayColType) -> Self {
    method array_col_type (line 310) | fn array_col_type(kind: &ArrayColType) -> ColumnType {
    method to_def (line 324) | fn to_def(&self, name: impl IntoIden) -> ColumnDef {
  type ArrayColType (line 282) | pub enum ArrayColType {
  function create_table (line 484) | pub async fn create_table(
  function create_join_table (line 506) | pub async fn create_join_table(
  function create_table_without_timestamps (line 531) | pub async fn create_table_without_timestamps(
  function create_join_table_without_timestamps (line 553) | pub async fn create_join_table_without_timestamps(
  function create_table_impl (line 562) | async fn create_table_impl(
  function normalize_table (line 692) | fn normalize_table(table: &str) -> String {
  function reference_id (line 697) | fn reference_id(totbl: &str) -> String {
  function add_column (line 709) | pub async fn add_column(
  function remove_column (line 733) | pub async fn remove_column(m: &SchemaManager<'_>, table: &str, name: &st...
  function add_reference (line 752) | pub async fn add_reference(
  function remove_reference (line 830) | pub async fn remove_reference(
  function drop_table (line 877) | pub async fn drop_table(m: &SchemaManager<'_>, table: &str) -> Result<()...
  function add_enum_values (line 891) | pub async fn add_enum_values(
  function drop_enum_type (line 931) | pub async fn drop_enum_type(m: &SchemaManager<'_>, enum_name: &str) -> R...

FILE: src/storage/contents.rs
  type Contents (line 4) | pub struct Contents {
    method from (line 14) | fn from(data: Bytes) -> Self {
  function from (line 21) | fn from(contents: Contents) -> Self {
  type Error (line 27) | type Error = std::string::FromUtf8Error;
  method try_from (line 35) | fn try_from(contents: Contents) -> Result<Self, Self::Error> {

FILE: src/storage/drivers/aws.rs
  type Credential (line 8) | pub struct Credential {
  function new (line 28) | pub fn new(bucket_name: &str, region: &str) -> StorageResult<Box<dyn Sto...
  function with_credentials_and_endpoint (line 54) | pub fn with_credentials_and_endpoint(
  function with_credentials (line 89) | pub fn with_credentials(
  function with_failure (line 112) | pub fn with_failure() -> Box<dyn StoreDriver> {

FILE: src/storage/drivers/azure.rs
  function new (line 17) | pub fn new(

FILE: src/storage/drivers/gcp.rs
  function new (line 17) | pub fn new(bucket_name: &str, credential_path: &str) -> StorageResult<Bo...

FILE: src/storage/drivers/local.rs
  function new (line 18) | pub fn new() -> Box<dyn StoreDriver> {
  function new_with_prefix (line 38) | pub fn new_with_prefix(prefix: impl AsRef<std::path::Path>) -> StorageRe...

FILE: src/storage/drivers/mem.rs
  function new (line 18) | pub fn new() -> Box<dyn StoreDriver> {

FILE: src/storage/drivers/mod.rs
  type UploadResponse (line 21) | pub struct UploadResponse {
  type GetResponse (line 30) | pub struct GetResponse {
    method new (line 35) | pub(crate) fn new(stream: Reader) -> Self {
    method bytes (line 44) | pub async fn bytes(&self) -> StorageResult<Bytes> {
    method into_stream (line 56) | pub async fn into_stream(self) -> StorageResult<BytesStream> {
  type StoreDriver (line 62) | pub trait StoreDriver: Sync + Send {
    method upload (line 69) | async fn upload(&self, path: &Path, content: &Bytes) -> StorageResult<...
    method get (line 76) | async fn get(&self, path: &Path) -> StorageResult<GetResponse>;
    method delete (line 84) | async fn delete(&self, path: &Path) -> StorageResult<()>;
    method rename (line 93) | async fn rename(&self, from: &Path, to: &Path) -> StorageResult<()>;
    method copy (line 100) | async fn copy(&self, from: &Path, to: &Path) -> StorageResult<()>;
    method exists (line 108) | async fn exists(&self, path: &Path) -> StorageResult<bool>;
    method get_stream (line 123) | async fn get_stream(&self, path: &Path) -> StorageResult<BytesStream> {
    method upload_stream (line 141) | async fn upload_stream(

FILE: src/storage/drivers/null.rs
  type NullStorage (line 15) | pub struct NullStorage {}
  function new (line 19) | pub fn new() -> Box<dyn StoreDriver> {
  method upload (line 31) | async fn upload(&self, _path: &Path, _content: &Bytes) -> StorageResult<...
  method get (line 42) | async fn get(&self, _path: &Path) -> StorageResult<GetResponse> {
  method delete (line 54) | async fn delete(&self, _path: &Path) -> StorageResult<()> {
  method rename (line 67) | async fn rename(&self, _from: &Path, _to: &Path) -> StorageResult<()> {
  method copy (line 78) | async fn copy(&self, _from: &Path, _to: &Path) -> StorageResult<()> {
  method exists (line 90) | async fn exists(&self, _path: &Path) -> StorageResult<bool> {

FILE: src/storage/drivers/opendal_adapter.rs
  type OpendalAdapter (line 11) | pub struct OpendalAdapter {
    method new (line 18) | pub fn new(opendal_impl: Operator) -> Self {
  method upload (line 34) | async fn upload(&self, path: &Path, content: &Bytes) -> StorageResult<Up...
  method get (line 50) | async fn get(&self, path: &Path) -> StorageResult<GetResponse> {
  method delete (line 64) | async fn delete(&self, path: &Path) -> StorageResult<()> {
  method rename (line 82) | async fn rename(&self, from: &Path, to: &Path) -> StorageResult<()> {
  method copy (line 103) | async fn copy(&self, from: &Path, to: &Path) -> StorageResult<()> {
  method exists (line 140) | async fn exists(&self, path: &Path) -> StorageResult<bool> {
  method get_stream (line 147) | async fn get_stream(&self, path: &Path) -> StorageResult<BytesStream> {
  method upload_stream (line 157) | async fn upload_stream(

FILE: src/storage/mod.rs
  type StorageError (line 28) | pub enum StorageError {
    method from (line 48) | fn from(val: opendal::Error) -> Self {
  type StorageResult (line 45) | pub type StorageResult<T> = std::result::Result<T, StorageError>;
  type Storage (line 53) | pub struct Storage {
    method single (line 69) | pub fn single(store: Box<dyn StoreDriver>) -> Self {
    method new (line 79) | pub fn new(
    method upload (line 108) | pub async fn upload(&self, path: &Path, content: &Bytes) -> StorageRes...
    method upload_with_strategy (line 123) | pub async fn upload_with_strategy(
    method download (line 156) | pub async fn download<T: TryFrom<contents::Contents>>(&self, path: &Pa...
    method download_with_policy (line 170) | pub async fn download_with_policy<T: TryFrom<contents::Contents>>(
    method delete (line 210) | pub async fn delete(&self, path: &Path) -> StorageResult<()> {
    method delete_with_policy (line 224) | pub async fn delete_with_policy(
    method rename (line 259) | pub async fn rename(&self, from: &Path, to: &Path) -> StorageResult<()> {
    method rename_with_policy (line 273) | pub async fn rename_with_policy(
    method copy (line 309) | pub async fn copy(&self, from: &Path, to: &Path) -> StorageResult<()> {
    method copy_with_policy (line 322) | pub async fn copy_with_policy(
    method as_store (line 348) | pub fn as_store(&self, name: &str) -> Option<&dyn StoreDriver> {
    method as_store_err (line 370) | pub fn as_store_err(&self, name: &str) -> StorageResult<&dyn StoreDriv...
    method download_stream (line 398) | pub async fn download_stream(&self, path: &Path) -> StorageResult<Byte...
    method download_stream_with_policy (line 409) | pub async fn download_stream_with_policy(
    method upload_stream (line 438) | pub async fn upload_stream(&self, path: &Path, stream: BytesStream) ->...
    method upload_stream_with_policy (line 449) | pub async fn upload_stream_with_policy(

FILE: src/storage/strategies/backup.rs
  type FailureMode (line 32) | pub enum FailureMode {
    method should_fail (line 275) | pub fn should_fail(&self, errors: &BTreeMap<String, String>) -> bool {
  type BackupStrategy (line 47) | pub struct BackupStrategy {
    method new (line 264) | pub fn new(primary: &str, secondaries: Option<Vec<String>>, failure_mo...
  method upload (line 61) | async fn upload(&self, storage: &Storage, path: &Path, content: &Bytes) ...
  method download (line 91) | async fn download(&self, storage: &Storage, path: &Path) -> StorageResul...
  method delete (line 103) | async fn delete(&self, storage: &Storage, path: &Path) -> StorageResult<...
  method rename (line 136) | async fn rename(&self, storage: &Storage, from: &Path, to: &Path) -> Sto...
  method copy (line 172) | async fn copy(&self, storage: &Storage, from: &Path, to: &Path) -> Stora...
  method download_stream (line 203) | async fn download_stream(
  method upload_stream (line 217) | async fn upload_stream(
  function upload_should_pass_when_backup_all_policy (line 296) | async fn upload_should_pass_when_backup_all_policy() {
  function upload_should_fail_when_primary_fail (line 331) | async fn upload_should_fail_when_primary_fail() {
  function upload_should_pass_when_allow_backup_failure_policy (line 366) | async fn upload_should_pass_when_allow_backup_failure_policy() {
  function upload_should_pass_when_at_least_one_failure_policy (line 401) | async fn upload_should_pass_when_at_least_one_failure_policy() {
  function upload_should_fail_when_at_least_one_failure_policy (line 436) | async fn upload_should_fail_when_at_least_one_failure_policy() {
  function upload_should_pass_count_fail_policy_should_pass (line 471) | async fn upload_should_pass_count_fail_policy_should_pass() {
  function upload_should_fail_when_count_fail_should_fail (line 506) | async fn upload_should_fail_when_count_fail_should_fail() {
  function can_download (line 542) | async fn can_download() {
  function delete_should_pass_when_backup_all_policy (line 571) | async fn delete_should_pass_when_backup_all_policy() {
  function rename_should_pass_when_backup_all_policy (line 608) | async fn rename_should_pass_when_backup_all_policy() {
  function rename_should_pass_when_allow_backup_failure_policy (line 659) | async fn rename_should_pass_when_allow_backup_failure_policy() {
  function rename_should_pass_when_at_least_one_failure_policy (line 712) | async fn rename_should_pass_when_at_least_one_failure_policy() {
  function rename_should_fail_when_at_least_one_failure_policy (line 765) | async fn rename_should_fail_when_at_least_one_failure_policy() {
  function rename_should_pass_when_count_fail_policy (line 819) | async fn rename_should_pass_when_count_fail_policy() {
  function rename_should_fail_when_count_fail_policy (line 872) | async fn rename_should_fail_when_count_fail_policy() {
  function copy_should_pass_when_backup_all_policy (line 928) | async fn copy_should_pass_when_backup_all_policy() {
  function copy_should_pass_when_allow_backup_failure_policy (line 979) | async fn copy_should_pass_when_allow_backup_failure_policy() {
  function copy_should_pass_when_at_least_one_failure_policy (line 1032) | async fn copy_should_pass_when_at_least_one_failure_policy() {
  function copy_should_fail_when_at_least_one_failure_policy (line 1085) | async fn copy_should_fail_when_at_least_one_failure_policy() {
  function copy_should_pass_when_count_fail_policy (line 1139) | async fn copy_should_pass_when_count_fail_policy() {
  function copy_should_fail_when_count_fail_policy (line 1192) | async fn copy_should_fail_when_count_fail_policy() {

FILE: src/storage/strategies/mirror.rs
  type FailureMode (line 31) | pub enum FailureMode {
    method should_fail (line 317) | pub fn should_fail(&self, errors: &BTreeMap<String, String>) -> bool {
  type MirrorStrategy (line 40) | pub struct MirrorStrategy {
    method new (line 296) | pub fn new(primary: &str, secondaries: Option<Vec<String>>, failure_mo...
    method try_download (line 305) | async fn try_download(
  method upload (line 63) | async fn upload(&self, storage: &Storage, path: &Path, content: &Bytes) ...
  method download (line 94) | async fn download(&self, storage: &Storage, path: &Path) -> StorageResul...
  method delete (line 122) | async fn delete(&self, storage: &Storage, path: &Path) -> StorageResult<...
  method rename (line 154) | async fn rename(&self, storage: &Storage, from: &Path, to: &Path) -> Sto...
  method copy (line 188) | async fn copy(&self, storage: &Storage, from: &Path, to: &Path) -> Stora...
  method download_stream (line 220) | async fn download_stream(
  method upload_stream (line 249) | async fn upload_stream(
  function upload_should_pass_with_mirror_all_policy (line 334) | async fn upload_should_pass_with_mirror_all_policy() {
  function upload_should_fail_with_mirror_all_policy (line 369) | async fn upload_should_fail_with_mirror_all_policy() {
  function upload_should_fail_when_allow_mirror_failure_policy (line 404) | async fn upload_should_fail_when_allow_mirror_failure_policy() {
  function can_download_when_primary_is_ok (line 438) | async fn can_download_when_primary_is_ok() {
  function can_download_when_primary_failed (line 475) | async fn can_download_when_primary_failed() {
  function rename_should_pass_when_primary_is_ok (line 519) | async fn rename_should_pass_when_primary_is_ok() {
  function rename_should_fail_when_primary_failed (line 570) | async fn rename_should_fail_when_primary_failed() {
  function rename_should_pass_when_allow_mirror_failure (line 615) | async fn rename_should_pass_when_allow_mirror_failure() {
  function copy_should_pass_when_primary_is_ok (line 666) | async fn copy_should_pass_when_primary_is_ok() {
  function copy_should_pass_fail_when_primary (line 717) | async fn copy_should_pass_fail_when_primary() {
  function should_pass_when_allow_mirror_failure (line 762) | async fn should_pass_when_allow_mirror_failure() {

FILE: src/storage/strategies/mod.rs
  type StorageStrategy (line 12) | pub trait StorageStrategy: Sync + Send {
    method upload (line 13) | async fn upload(&self, storage: &Storage, path: &Path, content: &Bytes...
    method download (line 14) | async fn download(&self, storage: &Storage, path: &Path) -> StorageRes...
    method delete (line 15) | async fn delete(&self, storage: &Storage, path: &Path) -> StorageResul...
    method rename (line 16) | async fn rename(&self, storage: &Storage, from: &Path, to: &Path) -> S...
    method copy (line 17) | async fn copy(&self, storage: &Storage, from: &Path, to: &Path) -> Sto...
    method download_stream (line 22) | async fn download_stream(&self, storage: &Storage, path: &Path) -> Sto...
    method upload_stream (line 27) | async fn upload_stream(

FILE: src/storage/strategies/single.rs
  type SingleStrategy (line 13) | pub struct SingleStrategy {
    method new (line 21) | pub fn new(primary: &str) -> Self {
  method upload (line 36) | async fn upload(&self, storage: &Storage, path: &Path, content: &Bytes) ...
  method download (line 49) | async fn download(&self, storage: &Storage, path: &Path) -> StorageResul...
  method delete (line 59) | async fn delete(&self, storage: &Storage, path: &Path) -> StorageResult<...
  method rename (line 68) | async fn rename(&self, storage: &Storage, from: &Path, to: &Path) -> Sto...
  method copy (line 80) | async fn copy(&self, storage: &Storage, from: &Path, to: &Path) -> Stora...
  method download_stream (line 89) | async fn download_stream(
  method upload_stream (line 102) | async fn upload_stream(
  function can_upload (line 125) | async fn can_upload() {
  function can_download (line 142) | async fn can_download() {
  function can_delete (line 160) | async fn can_delete() {
  function can_rename_file_path (line 181) | async fn can_rename_file_path() {
  function can_copy_file_path (line 210) | async fn can_copy_file_path() {

FILE: src/storage/stream.rs
  type BytesStream (line 10) | pub struct BytesStream {
    method from_reader (line 17) | pub(crate) async fn from_reader(reader: Reader) -> Result<Self, crate:...
    method collect (line 40) | pub async fn collect(mut self) -> Result<Bytes, std::io::Error> {
    method into_body (line 64) | pub fn into_body(self) -> axum::body::Body {
    method from_body_stream (line 73) | pub fn from_body_stream<S>(stream: S) -> Self
  type Item (line 53) | type Item = Result<Bytes, std::io::Error>;
  method poll_next (line 55) | fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Opt...

FILE: src/task.rs
  type Vars (line 13) | pub struct Vars {
    method from_cli_args (line 35) | pub fn from_cli_args(args: Vec<(String, String)>) -> Self {
    method cli_arg (line 58) | pub fn cli_arg(&self, key: &str) -> Result<&String> {
  type TaskInfo (line 68) | pub struct TaskInfo {
  type Task (line 75) | pub trait Task: Send + Sync {
    method task (line 77) | fn task(&self) -> TaskInfo;
    method run (line 79) | async fn run(&self, app_context: &AppContext, vars: &Vars) -> Result<()>;
  type Tasks (line 84) | pub struct Tasks {
    method list (line 91) | pub fn list(&self) -> Vec<TaskInfo> {
    method names (line 97) | pub fn names(&self) -> Vec<String> {
    method run (line 110) | pub async fn run(&self, app_context: &AppContext, task: &str, vars: &V...
    method register (line 120) | pub fn register(&mut self, task: impl Task + 'static) {
  function test_vars_from_cli_args (line 132) | async fn test_vars_from_cli_args() {
  function test_vars_cli_arg (line 145) | async fn test_vars_cli_arg() {
  function test_tasks_registry (line 154) | async fn test_tasks_registry() {
  function test_tasks_list (line 165) | async fn test_tasks_list() {
  function test_tasks_run_success (line 183) | async fn test_tasks_run_success() {
  function test_tasks_run_failure (line 195) | async fn test_tasks_run_failure() {
  function test_tasks_run_with_args (line 214) | async fn test_tasks_run_with_args() {
  function test_tasks_run_not_found (line 231) | async fn test_tasks_run_not_found() {
  function test_task_registration_and_override (line 248) | async fn test_task_registration_and_override() {

FILE: src/tera.rs
  function render_string (line 5) | pub fn render_string(tera_template: &str, locals: &serde_json::Value) ->...

FILE: src/testing/db.rs
  function seed (line 36) | pub async fn seed<H: Hooks>(ctx: &AppContext) -> Result<()> {
  function init_test_db_creation (line 45) | pub fn init_test_db_creation(conn_str: &str) -> Result<Box<dyn TestSuppo...
  type TestSupport (line 55) | pub trait TestSupport: Send + Sync {
    method init_db (line 57) | fn init_db<'a>(&'a self) -> Pin<Box<dyn Future<Output = ()> + Send + '...
    method get_connection_str (line 59) | fn get_connection_str(&self) -> &str;
    method cleanup_db (line 61) | fn cleanup_db(&self);
    method get_connection_str (line 92) | fn get_connection_str(&self) -> &str {
    method init_db (line 96) | fn init_db<'a>(&'a self) -> Pin<Box<dyn Future<Output = ()> + Send + '...
    method cleanup_db (line 110) | fn cleanup_db(&self) {
    method get_connection_str (line 167) | fn get_connection_str(&self) -> &str {
    method init_db (line 170) | fn init_db<'a>(&'a self) -> Pin<Box<dyn Future<Output = ()> + Send + '...
    method cleanup_db (line 174) | fn cleanup_db(&self) {
    method get_connection_str (line 192) | fn get_connection_str(&self) -> &str {
    method init_db (line 195) | fn init_db<'a>(&'a self) -> Pin<Box<dyn Future<Output = ()> + Send + '...
    method cleanup_db (line 199) | fn cleanup_db(&self) {}
  type PostgresTest (line 64) | pub struct PostgresTest {
    method new (line 75) | pub fn new(conn_str: &str) -> Result<Self> {
  type SqliteTest (line 131) | pub struct SqliteTest {
    method new (line 142) | pub fn new(conn_str: &str) -> Result<Self> {
  type Any (line 179) | pub struct Any {
    method new (line 184) | pub fn new(conn_str: &str) -> Self {
  function schema_exists (line 209) | async fn schema_exists(pool: &sqlx::PgPool, schema_name: &str) -> bool {
  function sqlite_test_support (line 222) | async fn sqlite_test_support() {
  function postgres_test_support (line 234) | async fn postgres_test_support() {

FILE: src/testing/redaction.rs
  function get_cleanup_user_model (line 8) | pub fn get_cleanup_user_model() -> &'static Vec<(&'static str, &'static ...
  function get_cleanup_date (line 21) | pub fn get_cleanup_date() -> &'static Vec<(&'static str, &'static str)> {
  function get_cleanup_model (line 34) | pub fn get_cleanup_model() -> &'static Vec<(&'static str, &'static str)> {
  function get_cleanup_mail (line 38) | pub fn get_cleanup_mail() -> &'static Vec<(&'static str, &'static str)> {
  function cleanup_user_model (line 90) | pub fn cleanup_user_model() -> Vec<(&'static str, &'static str)> {
  function cleanup_email (line 99) | pub fn cleanup_email() -> Vec<(&'static str, &'static str)> {

FILE: src/testing/request.rs
  type BootResultWrapper (line 20) | pub struct BootResultWrapper {
    method new (line 28) | pub fn new(boot: BootResult, test_db: Box<dyn super::db::TestSupport>)...
  type Target (line 38) | type Target = BootResult;
  method deref (line 40) | fn deref(&self) -> &Self::Target {
  method drop (line 47) | fn drop(&mut self) {
  type RequestConfig (line 53) | pub struct RequestConfig {
  method default (line 63) | fn default() -> Self {
  type RequestConfigBuilder (line 69) | pub struct RequestConfigBuilder {
    method new (line 78) | pub fn new() -> Self {
    method save_cookies (line 88) | pub fn save_cookies(mut self, save: bool) -> Self {
    method default_content_type (line 95) | pub fn default_content_type<S: Into<String>>(mut self, content_type: S...
    method default_scheme (line 102) | pub fn default_scheme<S: Into<String>>(mut self, scheme: S) -> Self {
    method build (line 109) | pub fn build(self) -> RequestConfig {
  method default (line 119) | fn default() -> Self {
  method from (line 126) | fn from(request_config: RequestConfig) -> Self {
  constant TEST_PORT_SERVER (line 136) | pub const TEST_PORT_SERVER: i32 = 5555;
  constant TEST_BINDING_SERVER (line 139) | pub const TEST_BINDING_SERVER: &str = "localhost";
  function get_base_url_port (line 143) | pub fn get_base_url_port(port: i32) -> String {
  function get_available_port (line 152) | pub async fn get_available_port() -> i32 {
  function boot_test (line 185) | pub async fn boot_test<H: Hooks>() -> Result<BootResult> {
  function boot_test_with_create_db (line 209) | pub async fn boot_test_with_create_db<H: Hooks>() -> Result<BootResultWr...
  function boot_test_unique_port (line 248) | pub async fn boot_test_unique_port<H: Hooks>(port: Option<i32>) -> Resul...
  function request_internal (line 259) | async fn request_internal<F, Fut>(callback: F, boot: &BootResult, test_s...
  function request (line 302) | pub async fn request<H: Hooks, F, Fut>(callback: F)
  function request_with_create_db (line 331) | pub async fn request_with_create_db<H: Hooks, F, Fut>(callback: F)
  function request_with_config (line 355) | pub async fn request_with_config<H: Hooks, F, Fut>(config: RequestConfig...
  function request_config_with_create_db (line 382) | pub async fn request_config_with_create_db<H: Hooks, F, Fut>(config: Req...

FILE: src/testing/selector.rs
  function assert_css_exists (line 24) | pub fn assert_css_exists(html: &str, selector: &str) {
  function assert_css_not_exists (line 54) | pub fn assert_css_not_exists(html: &str, selector: &str) {
  function assert_css_eq (line 84) | pub fn assert_css_eq(html: &str, selector: &str, expected_text: &str) {
  function assert_link (line 126) | pub fn assert_link(html: &str, selector: &str, expected_href: &str) {
  function assert_attribute_exists (line 155) | pub fn assert_attribute_exists(html: &str, selector: &str, attribute: &s...
  function assert_attribute_eq (line 198) | pub fn assert_attribute_eq(html: &str, selector: &str, attribute: &str, ...
  function assert_count (line 245) | pub fn assert_count(html: &str, selector: &str, expected_count: usize) {
  function assert_css_eq_list (line 283) | pub fn assert_css_eq_list(html: &str, selector: &str, expected_texts: &[...
  function select (line 322) | pub fn select(html: &str, selector: &str) -> Vec<String> {
  function setup_test_html (line 336) | fn setup_test_html() -> &'static str {
  function test_assert_css_exists (line 373) | fn test_assert_css_exists() {
  function test_assert_css_not_exists (line 392) | fn test_assert_css_not_exists() {
  function test_assert_css_eq (line 411) | fn test_assert_css_eq() {
  function test_assert_link (line 431) | fn test_assert_link() {
  function test_assert_attribute_exists (line 452) | fn test_assert_attribute_exists() {
  function test_assert_attribute_eq (line 471) | fn test_assert_attribute_eq() {
  function test_assert_count (line 492) | fn test_assert_count() {
  function test_assert_css_eq_list (line 511) | fn test_assert_css_eq_list() {
  function test_assert_css_eq_list_table (line 533) | fn test_assert_css_eq_list_table() {
  function test_select (line 560) | fn test_select() {

FILE: src/tests_cfg/app.rs
  function get_app_context (line 9) | pub async fn get_app_context() -> AppContext {

FILE: src/tests_cfg/config.rs
  function test_config (line 12) | pub fn test_config() -> Config {
  function get_database_config (line 66) | pub fn get_database_config() -> config::Database {
  function get_sqlite_test_config (line 90) | pub fn get_sqlite_test_config(db_filename: &str) -> (config::Database, T...

FILE: src/tests_cfg/controllers/auth.rs
  function routes (line 4) | pub fn routes() -> Routes {

FILE: src/tests_cfg/controllers/home.rs
  function routes (line 4) | pub fn routes() -> Routes {

FILE: src/tests_cfg/db.rs
  function get_value (line 27) | pub async fn get_value(conn: &sea_orm::DatabaseConnection, query: &str) ...
  function dummy_connection (line 55) | pub async fn dummy_connection() -> sea_orm::DatabaseConnection {
  function fail_connection (line 67) | pub async fn fail_connection() -> sea_orm::DatabaseConnection {
  type Model (line 84) | pub struct Model {
  type Loco (line 93) | pub enum Loco {
  method unquoted (line 100) | fn unquoted(&self, s: &mut dyn fmt::Write) {
  type Relation (line 115) | pub enum Relation {}
  type Migrator (line 121) | pub struct Migrator;
  method migrations (line 125) | fn migrations() -> Vec<Box<dyn MigrationTrait>> {
  type AppHook (line 131) | pub struct AppHook;
  method app_version (line 134) | fn app_version() -> String {
  method app_name (line 138) | fn app_name() -> &'static str {
  method initializers (line 142) | async fn initializers(_ctx: &AppContext) -> Result<Vec<Box<dyn Initializ...
  method routes (line 146) | fn routes(_ctx: &AppContext) -> AppRoutes {
  method boot (line 150) | async fn boot(
  method connect_workers (line 158) | async fn connect_workers(_ctx: &AppContext, _q: &Queue) -> Result<()> {
  method register_tasks (line 162) | fn register_tasks(tasks: &mut Tasks) {
  method truncate (line 167) | async fn truncate(_ctx: &AppContext) -> Result<()> {
  method seed (line 171) | async fn seed(_ctx: &AppContext, _base: &Path) -> Result<()> {

FILE: src/tests_cfg/postgres.rs
  function setup_postgres_container (line 18) | pub async fn setup_postgres_container() -> (String, ContainerAsync<Gener...

FILE: src/tests_cfg/queue.rs
  function queue_jobs_fixture_path (line 6) | fn queue_jobs_fixture_path() -> PathBuf {
  function postgres_seed_data (line 19) | pub async fn postgres_seed_data(pool: &sqlx::PgPool) {
  function sqlite_seed_data (line 49) | pub async fn sqlite_seed_data(pool: &sqlx::Pool<sqlx::Sqlite>) {

FILE: src/tests_cfg/redis.rs
  function setup_redis_container (line 18) | pub async fn setup_redis_container() -> (String, ContainerAsync<GenericI...

FILE: src/tests_cfg/task.rs
  type Foo (line 4) | pub struct Foo;
  method task (line 8) | fn task(&self) -> TaskInfo {
  method run (line 14) | async fn run(&self, _app_context: &AppContext, _vars: &task::Vars) -> Re...
  type ParseArgs (line 21) | pub struct ParseArgs;
  method task (line 25) | fn task(&self) -> TaskInfo {
  method run (line 31) | async fn run(&self, _app_context: &AppContext, vars: &task::Vars) -> Res...

FILE: src/validation.rs
  type ModelValidationMessage (line 52) | pub struct ModelValidationMessage {
  type ValidationError (line 67) | pub struct ValidationError {
  type ModelValidationErrors (line 76) | pub struct ModelValidationErrors {
    method from (line 81) | fn from(value: ValidationErrors) -> Self {
  method from (line 104) | fn from(errors: ModelValidationErrors) -> Self {
  function into_db_error (line 111) | pub fn into_db_error(errors: &ModelValidationErrors) -> sea_orm::DbErr {
  type ValidatorTrait (line 137) | pub trait ValidatorTrait {
    method validate (line 143) | fn validate(&self) -> Result<(), ModelValidationErrors>;
    method validate (line 148) | fn validate(&self) -> Result<(), ModelValidationErrors> {
    method validate (line 207) | fn validate(&self) -> Result<(), ModelValidationErrors> {
  type Validatable (line 155) | pub trait Validatable {
    method validate (line 161) | fn validate(&self) -> Result<(), ModelValidationErrors> {
    method validator (line 165) | fn validator(&self) -> Box<dyn validator::Validate>;
  type TestValidator (line 179) | pub struct TestValidator {
  function can_validate_into_db_error (line 188) | fn can_validate_into_db_error(#[case] name: &str) {
  type CustomValidator (line 202) | pub struct CustomValidator {
  function custom_validator_works (line 227) | fn custom_validator_works(#[case] name: &str) {

FILE: tests/build_scripts/embedded_assets.rs
  function create_test_assets (line 17) | fn create_test_assets() -> tree_fs::Tree {
  function create_insta_settings (line 29) | fn create_insta_settings(root_path: &Path) -> insta::Settings {
  function test_generate_empty_asset_files (line 37) | fn test_generate_empty_asset_files() {
  function test_generate_asset_code (line 69) | fn test_generate_asset_code() {
  function test_discover_all_directories (line 121) | fn test_discover_all_directories() {
  function test_find_app_directory (line 163) | fn test_find_app_directory() {
  function test_build_static_assets (line 209) | fn test_build_static_assets() {
  function test_collect_all_files (line 253) | fn test_collect_all_files() {
  function test_template_inheritance (line 293) | fn test_template_inheritance() {

FILE: tests/controller/extractor/auth/api_token.rs
  type TestUserResponse (line 9) | pub struct TestUserResponse {
  type TestUser (line 17) | struct TestUser {
  method find_by_claims_key (line 24) | async fn find_by_claims_key(
  method find_by_api_key (line 39) | async fn find_by_api_key(
  function api_token_handler (line 56) | async fn api_token_handler(auth: auth::ApiToken<TestUser>) -> Result<Res...
  function can_extract_api_token_valid (line 66) | async fn can_extract_api_token_valid() {
  function can_handle_api_token_invalid (line 93) | async fn can_handle_api_token_invalid() {
  function can_handle_api_token_missing (line 115) | async fn can_handle_api_token_missing() {
  function test_user_response_serialization (line 136) | async fn test_user_response_serialization() {

FILE: tests/controller/extractor/auth/jwt.rs
  type TestResponse (line 7) | pub struct TestResponse {
  function jwt_handler (line 12) | async fn jwt_handler(auth: auth::JWT) -> Result<Response> {
  function can_extract_jwt_with_valid_token (line 20) | async fn can_extract_jwt_with_valid_token() {
  function can_handle_invalid_jwt_token (line 54) | async fn can_handle_invalid_jwt_token() {
  function can_handle_missing_jwt_token (line 82) | async fn can_handle_missing_jwt_token() {
  function can_handle_expired_jwt_token (line 109) | async fn can_handle_expired_jwt_token() {
  function can_handle_malformed_authorization_header (line 142) | async fn can_handle_malformed_authorization_header() {
  function can_handle_missing_jwt_configuration (line 170) | async fn can_handle_missing_jwt_configuration() {
  function can_extract_jwt_from_cookie (line 192) | async fn can_extract_jwt_from_cookie() {
  function can_extract_jwt_from_query (line 236) | async fn can_extract_jwt_from_query() {
  function can_extract_jwt_with_multiple_locations_cookie_fallback (line 279) | async fn can_extract_jwt_with_multiple_locations_cookie_fallback() {
  function can_extract_jwt_with_multiple_locations_query_fallback (line 325) | async fn can_extract_jwt_with_multiple_locations_query_fallback() {
  function can_handle_multiple_locations_all_fail (line 370) | async fn can_handle_multiple_locations_all_fail() {
  function can_handle_cookie_location_missing_cookie (line 407) | async fn can_handle_cookie_location_missing_cookie() {
  function can_handle_query_location_missing_param (line 441) | async fn can_handle_query_location_missing_param() {
  function can_handle_jwt_with_wrong_algorithm (line 475) | async fn can_handle_jwt_with_wrong_algorithm() {
  function can_handle_jwt_with_invalid_signature (line 511) | async fn can_handle_jwt_with_invalid_signature() {
  function can_handle_malformed_jwt_structure (line 552) | async fn can_handle_malformed_jwt_structure() {
  function can_extract_jwt_from_cookie_with_special_chars (line 580) | async fn can_extract_jwt_from_cookie_with_special_chars() {
  function can_handle_cookie_with_empty_value (line 624) | async fn can_handle_cookie_with_empty_value() {
  function can_extract_jwt_from_query_with_special_chars (line 658) | async fn can_extract_jwt_from_query_with_special_chars() {
  function can_handle_query_with_empty_value (line 701) | async fn can_handle_query_with_empty_value() {
  function can_handle_query_with_spaces (line 734) | async fn can_handle_query_with_spaces() {
  function can_validate_error_message_for_missing_token (line 770) | async fn can_validate_error_message_for_missing_token() {
  function can_validate_error_message_for_invalid_token (line 802) | async fn can_validate_error_message_for_invalid_token() {
  function can_validate_error_message_for_malformed_header (line 835) | async fn can_validate_error_message_for_malformed_header() {
  function can_handle_jwt_expires_exactly_at_current_time (line 868) | async fn can_handle_jwt_expires_exactly_at_current_time() {
  function can_handle_jwt_expired_one_second_ago (line 903) | async fn can_handle_jwt_expired_one_second_ago() {
  function can_handle_jwt_expires_in_one_second (line 941) | async fn can_handle_jwt_expires_in_one_second() {
  function can_handle_jwt_with_missing_exp_claim (line 980) | async fn can_handle_jwt_with_missing_exp_claim() {
  function can_handle_jwt_with_invalid_exp_claim (line 1016) | async fn can_handle_jwt_with_invalid_exp_claim() {
  function can_handle_jwt_with_distant_future_expiration (line 1052) | async fn can_handle_jwt_with_distant_future_expiration() {
  function can_handle_jwt_with_epoch_expiration (line 1095) | async fn can_handle_jwt_with_epoch_expiration() {

FILE: tests/controller/extractor/auth/jwt_with_user.rs
  type TestUserResponse (line 9) | pub struct TestUserResponse {
  type TestUser (line 17) | struct TestUser {
  method find_by_claims_key (line 24) | async fn find_by_claims_key(
  method find_by_api_key (line 39) | async fn find_by_api_key(
  function jwt_with_user_handler (line 56) | async fn jwt_with_user_handler(auth: auth::JWTWithUser<TestUser>) -> Res...
  function can_extract_jwt_with_user_valid_token (line 66) | async fn can_extract_jwt_with_user_valid_token() {
  function can_handle_jwt_with_user_invalid_token (line 109) | async fn can_handle_jwt_with_user_invalid_token() {
  function can_handle_jwt_with_user_nonexistent_user (line 141) | async fn can_handle_jwt_with_user_nonexistent_user() {
  function can_handle_jwt_with_user_missing_token (line 179) | async fn can_handle_jwt_with_user_missing_token() {

FILE: tests/controller/extractor/shared_store.rs
  type MySharedData (line 9) | struct MySharedData {
  type MySharedDataWithoutClone (line 13) | struct MySharedDataWithoutClone {
  function test_shared_store_extractor (line 21) | async fn test_shared_store_extractor(#[case] exists: bool) {
  function test_shared_store_without_clone (line 58) | async fn test_shared_store_without_clone() {

FILE: tests/controller/extractor/validate.rs
  type Data (line 8) | pub struct Data {
  function validation_with_response (line 15) | async fn validation_with_response(
  function simple_validation (line 21) | async fn simple_validation(JsonValidate(_params): JsonValidate<Data>) ->...
  function can_validation_with_response (line 26) | async fn can_validation_with_response() {
  function can_validation_without_response (line 61) | async fn can_validation_without_response() {

FILE: tests/controller/from_ref.rs
  function can_extract_db_connection_from_app_context (line 18) | async fn can_extract_db_connection_from_app_context() {
  function can_extract_cache_from_app_context (line 45) | async fn can_extract_cache_from_app_context() {
  function can_extract_shared_store_from_app_context (line 72) | async fn can_extract_shared_store_from_app_context() {

FILE: tests/controller/into_response.rs
  function not_found (line 7) | async fn not_found() {
  function internal_server_error (line 38) | async fn internal_server_error() {
  function unauthorized (line 69) | async fn unauthorized() {
  function fallback (line 100) | async fn fallback() {
  function custom_error (line 131) | async fn custom_error() {
  function json_rejection (line 169) | async fn json_rejection() {

FILE: tests/controller/middlewares.rs
  function panic (line 23) | async fn panic(#[case] enable: bool) {
  function etag (line 56) | async fn etag(#[case] enable: bool) {
  function remote_ip (line 88) | async fn remote_ip(#[case] enable: bool, #[case] expected: &str) {
  function timeout (line 123) | async fn timeout(#[case] enable: bool) {
  function cors (line 158) | async fn cors(
  function limit_payload (line 222) | async fn limit_payload(#[case] limit: middleware::limit_payload::Default...
  function static_assets (line 254) | async fn static_assets() {
  function secure_headers (line 317) | async fn secure_headers(
  function fallback (line 367) | async fn fallback(
  function powered_by_header (line 437) | async fn powered_by_header(#[case] ident: Option<String>) {

FILE: tests/infra_cfg/server.rs
  function get_action (line 12) | async fn get_action() -> Result<Response> {
  function post_action (line 17) | async fn post_action(_body: axum::body::Bytes) -> Result<Response> {
  function start_from_boot (line 26) | pub async fn start_from_boot(
  function start_from_ctx (line 49) | pub async fn start_from_ctx(ctx: AppContext, port: Option<i32>) -> tokio...
  function start_with_route (line 71) | pub async fn start_with_route(

FILE: xtask/src/bin/main.rs
  type Cli (line 13) | struct Cli {
  type Commands (line 19) | enum Commands {
  function main (line 39) | fn main() -> eyre::Result<()> {

FILE: xtask/src/bump_version.rs
  function get_replace_loco_lib_version (line 21) | fn get_replace_loco_lib_version() -> &'static Regex {
  function get_replace_loco_package_version (line 30) | fn get_replace_loco_package_version() -> &'static Regex {
  type BumpVersion (line 34) | pub struct BumpVersion {
    method run (line 45) | pub fn run(&self) -> Result<()> {
    method bump_loco_framework (line 89) | fn bump_loco_framework(&self, path: &str) -> Result<()> {
    method bump_subcrates_version (line 115) | fn bump_subcrates_version(&self, crates: &[&str]) -> Result<()> {
    method modify_starters_loco_version (line 160) | pub fn modify_starters_loco_version(&self, replace_with: &str) -> Resu...
    method replace_loco_rs_version (line 171) | fn replace_loco_rs_version(path: &Path, replace_with: &str) -> Result<...

FILE: xtask/src/ci.rs
  constant FMT_TEST (line 10) | const FMT_TEST: [&str; 3] = ["test", "--all-features", "--all"];
  constant FMT_ARGS (line 11) | const FMT_ARGS: [&str; 2] = ["fmt", "--all"];
  constant FMT_CLIPPY (line 12) | const FMT_CLIPPY: [&str; 8] = [
  type RunResults (line 24) | pub struct RunResults {
    method is_valid (line 33) | pub fn is_valid(&self) -> bool {
  function all_resources (line 42) | pub fn all_resources(base_dir: &Path) -> Result<Vec<RunResults>> {
  function run_all_in_folder (line 58) | pub fn run_all_in_folder(root_folder: &Path) -> Result<Vec<RunResults>> {
  function run (line 74) | pub fn run(dir: &Path) -> Option<RunResults> {
  function cargo_test (line 88) | pub fn cargo_test(dir: &Path, serial: bool) -> Result<Output> {
  function cargo_fmt (line 104) | pub fn cargo_fmt(dir: &Path) -> Result<Output> {
  function cargo_clippy (line 114) | pub fn cargo_clippy(dir: &Path) -> Result<Output> {

FILE: xtask/src/errors.rs
  type Error (line 3) | pub enum Error {
  type Result (line 18) | pub type Result<T> = std::result::Result<T, Error>;

FILE: xtask/src/lib.rs
  type CmdExit (line 11) | pub struct CmdExit {
    method error_with_message (line 18) | pub fn error_with_message(message: &str) -> Self {
    method ok_with_message (line 26) | pub fn ok_with_message(message: &str) -> Self {
    method ok (line 34) | pub const fn ok() -> Self {
    method exit (line 41) | pub fn exit(&self) {

FILE: xtask/src/out.rs
  function print_ci_results (line 5) | pub fn print_ci_results(result: &Vec<RunResults>) -> String {

FILE: xtask/src/prompt.rs
  function confirmation (line 5) | pub fn confirmation(message: &str) -> eyre::Result<bool> {

FILE: xtask/src/utils.rs
  constant FOLDER_EXAMPLES (line 6) | pub const FOLDER_EXAMPLES: &str = "examples";
  constant FOLDER_STARTERS (line 7) | pub const FOLDER_STARTERS: &str = "starters";
  constant FOLDER_LOCO_CLI (line 8) | pub const FOLDER_LOCO_CLI: &str = "loco-cli";
  function get_cargo_folders (line 14) | pub fn get_cargo_folders(path: &Path) -> std::io::Result<Vec<PathBuf>> {

FILE: xtask/src/versions.rs
  function bump_version_in_file (line 14) | fn bump_version_in_file(
  function bump_version (line 43) | pub fn bump_version(version: &str) -> Result<()> {
Condensed preview — 794 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,721K chars).
[
  {
    "path": ".cargo/config.toml",
    "chars": 187,
    "preview": "[alias]\n\nxtask = \"run --package xtask --\"\n\n# https://github.com/rust-lang/rust/issues/141626\n# (can be removed once link"
  },
  {
    "path": ".clippy.toml",
    "chars": 36,
    "preview": "cognitive-complexity-threshold = 40\n"
  },
  {
    "path": ".gitattributes",
    "chars": 49,
    "preview": "* linguist-vendored\n*.rs linguist-vendored=false\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 16,
    "preview": "github: loco-rs "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 1091,
    "preview": "---\nname: Bug Report\nabout: Report behavior that deviates from specification or expectation\ntitle: \"\"\nlabels: assessment"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 190,
    "preview": "blank_issues_enabled: true\ncontact_links:\n  - name: Question\n    url: https://github.com/loco-rs/loco/discussions\n    ab"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "chars": 544,
    "preview": "---\nname: Feature Request\nabout: Suggest a new feature\ntitle: \"\"\nlabels: enhancement\nassignees: \"\"\n---\n\n## Feature Reque"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/suggestion.md",
    "chars": 940,
    "preview": "---\nname: Suggestion\nabout: Suggest a change or improvement to existing functionality\n\ntitle: \"\"\nlabels: assessment\nassi"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 242,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"cargo\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n    open-pul"
  },
  {
    "path": ".github/workflows/docs.yml",
    "chars": 564,
    "preview": "name: \"[docs]\"\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n\nenv:\n  RUST_TOOLCHAIN: stable\n  TOOLCHAIN_PROF"
  },
  {
    "path": ".github/workflows/loco-gen-ci.yml",
    "chars": 1941,
    "preview": "name: \"[loco-gen:ci]\"\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - \"loco-gen/**\"\n  pull_request:\n    pat"
  },
  {
    "path": ".github/workflows/loco-gen-deploy.yml",
    "chars": 1301,
    "preview": "name: \"[loco-gen-deploy]\"\non:\n  schedule:\n    - cron: \"0 0 * * *\"\n\nenv:\n  RUST_TOOLCHAIN: stable\n  TOOLCHAIN_PROFILE: mi"
  },
  {
    "path": ".github/workflows/loco-new.yml",
    "chars": 2115,
    "preview": "name: \"[loco-new:ci]\"\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - \"loco-new/**\"\n      - \"loco-gen/**\"\n "
  },
  {
    "path": ".github/workflows/loco-rs-ci-sanity.yml",
    "chars": 1635,
    "preview": "# To optimize CI runtime:\n# A simpler \"sanity check\" workflow is introduced. \n# This workflow only runs if changes in th"
  },
  {
    "path": ".github/workflows/loco-rs-ci.yml",
    "chars": 2073,
    "preview": "name: \"[loco_rs:ci]\"\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n\nenv:\n  RUST_TOOLCHAIN: stable\n  TOOLCHAI"
  },
  {
    "path": ".gitignore",
    "chars": 1048,
    "preview": "# local dev\ntodo.txt\ntodo.md\nexamples/demo2\nexamples/myapp\n*.sqlite\n*.sqlite-wal\n*.sqlite-shm\n\n*.sqlite3\n*.sqlite3-wal\n*"
  },
  {
    "path": ".rustfmt.toml",
    "chars": 49,
    "preview": "max_width = 100\nuse_small_heuristics = \"Default\"\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 62027,
    "preview": "# Changelog\n\n\n\n##  Unreleased\n- Fix `cargo fmt` error in `loco-new` ([#1669](https://github.com/loco-rs/loco/pull/1669))"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5228,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 4827,
    "preview": "# Contributing to Loco\n\nThank you for taking the time to read this.\n\nThe first way to show support is to star our repos "
  },
  {
    "path": "Cargo.toml",
    "chars": 5713,
    "preview": "[workspace]\nmembers = [\"xtask\", \"loco-gen\"]\nexclude = [\"starters\"]\n\n[workspace.package]\nedition = \"2021\"\nrust-version = "
  },
  {
    "path": "DEVELOPMENT.md",
    "chars": 5313,
    "preview": "## Blessed dependencies maintenance and `loco doctor`\n\nLoco contain a few major and \"blessed\" dependencies, these appear"
  },
  {
    "path": "LICENSE",
    "chars": 10946,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README-pt_BR.md",
    "chars": 5648,
    "preview": " <div align=\"center\">\n\n   <img src=\"https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac\"/>"
  },
  {
    "path": "README-zh_CN.md",
    "chars": 1250,
    "preview": " <div align=\"center\">\n\n   <img src=\"https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac\"/>"
  },
  {
    "path": "README.es.md",
    "chars": 5682,
    "preview": "<div align=\"center\">\n\n   <img src=\"https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac\"/>\n"
  },
  {
    "path": "README.fr.md",
    "chars": 5942,
    "preview": " <div align=\"center\">\n\n   <img src=\"https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac\"/>"
  },
  {
    "path": "README.ja.md",
    "chars": 3481,
    "preview": "<div align=\"center\">\n\n   <img src=\"https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac\"/>\n"
  },
  {
    "path": "README.ko.md",
    "chars": 3965,
    "preview": " <div align=\"center\">\n\n   <img src=\"https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac\"/>"
  },
  {
    "path": "README.md",
    "chars": 5284,
    "preview": " <div align=\"center\">\n\n   <img src=\"https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac\"/>"
  },
  {
    "path": "README.ru.md",
    "chars": 5360,
    "preview": " <div align=\"center\">\n\n   <img src=\"https://github.com/loco-rs/loco/assets/83390/992d215a-3cd3-42ee-a1c7-de9fd25a5bac\"/>"
  },
  {
    "path": "SECURITY.md",
    "chars": 376,
    "preview": "# Security Policy\n\nBy researching and submitting a vulnerability, you'll be helping open source and this project's goal "
  },
  {
    "path": "build/embedded_assets.rs",
    "chars": 14803,
    "preview": "use std::collections::{HashMap, HashSet};\nuse std::{\n    env,\n    fs::{self, File},\n    io::{self, Write},\n    path::{Pa"
  },
  {
    "path": "build.rs",
    "chars": 917,
    "preview": "#[cfg(feature = \"embedded_assets\")]\nuse std::{env, path::Path};\n\nfn main() {\n    #[cfg(feature = \"embedded_assets\")]\n   "
  },
  {
    "path": "docs-site/.gitignore",
    "chars": 21,
    "preview": "public/\nnode_modules/"
  },
  {
    "path": "docs-site/config.toml",
    "chars": 6026,
    "preview": "# The URL the site will be built for\nbase_url = \"https://loco.rs\"\ntitle = \"Loco.rs - Productivity-first Rust Fullstack W"
  },
  {
    "path": "docs-site/content/_index.md",
    "chars": 1455,
    "preview": "+++\ntitle = \"Loco\"\n\n\n# The homepage contents\n[extra]\nlead = 'The <em>one-person framework</em> for Rust for side-project"
  },
  {
    "path": "docs-site/content/authors/_index.md",
    "chars": 422,
    "preview": "+++\ntitle = \"Authors\"\ndescription = \"The authurs of the blog articles.\"\ndraft = false\n\n# If add a new author page in thi"
  },
  {
    "path": "docs-site/content/authors/limpidcrypto.md",
    "chars": 300,
    "preview": "+++\r\ntitle = \"LimpidCrypto\"\r\ndescription = \"Building open source tools for cryptocurrency development\"\r\ndate = 2024-01-2"
  },
  {
    "path": "docs-site/content/authors/team-loco.md",
    "chars": 310,
    "preview": "+++\ntitle = \"Team Loco\"\ndescription = \"Creators of the Loco framework\"\ndate = 2021-04-01T08:50:45+00:00\nupdated = 2021-0"
  },
  {
    "path": "docs-site/content/blog/_index.md",
    "chars": 109,
    "preview": "+++\ntitle = \"Blog\"\ndescription = \"Blog\"\nsort_by = \"date\"\npaginate_by = 10\ntemplate = \"blog/section.html\"\n+++\n"
  },
  {
    "path": "docs-site/content/blog/angular-frontend.md",
    "chars": 2974,
    "preview": "+++\r\ntitle = \"Creating Frontend Website Using Angular\"\r\ndescription = \"Setting up a Loco app for serving an Angular clie"
  },
  {
    "path": "docs-site/content/blog/axum-session.md",
    "chars": 5585,
    "preview": "+++\ntitle = \"Building a Rust App with Axum Session\"\ndescription = \"Add sessions to your app with Axum Sessions. Configur"
  },
  {
    "path": "docs-site/content/blog/deploy-aws.md",
    "chars": 16047,
    "preview": "+++\ntitle = \"Deploying Rust App with Terraform on AWS Fargate\"\ndescription = \"Learn how to deploy a Loco app with Terraf"
  },
  {
    "path": "docs-site/content/blog/frontend-website.md",
    "chars": 6151,
    "preview": "+++\ntitle = \"Creating Frontend Website\"\ndescription = \"Build a REST API quickly with Loco and then follow by building a "
  },
  {
    "path": "docs-site/content/blog/hello-world.md",
    "chars": 3876,
    "preview": "+++\ntitle = \"What if Rails was Built on Rust?\"\ndescription = \"Introducing Loco: a Rails-inspired Rust web framework. See"
  },
  {
    "path": "docs-site/content/casts/001-dynamic-responses-and-content-types.md",
    "chars": 650,
    "preview": "+++\ntitle = \"Dynamic responses and content types\"\ndescription = \"Learn how to respond to incoming requests with the appr"
  },
  {
    "path": "docs-site/content/casts/002-routes-and-prefixes.md",
    "chars": 614,
    "preview": "+++\ntitle = \"Routes and prefixes\"\ndescription = \"Routes in Loco are derived from how Axum does Routes. Learn how to shap"
  },
  {
    "path": "docs-site/content/casts/003-scaffolding-crud-with-html.md",
    "chars": 741,
    "preview": "+++\ntitle = \"Scaffolding full CRUD with HTML views\"\ndescription = \"Loco generators are very powerful. Generate a full CR"
  },
  {
    "path": "docs-site/content/casts/004-creating-tasks.md",
    "chars": 766,
    "preview": "+++\ntitle = \"Creating tasks\"\ndescription = \"Ever reached out to write a small script to reset a user password? send emai"
  },
  {
    "path": "docs-site/content/casts/005-testing-tasks.md",
    "chars": 846,
    "preview": "+++\ntitle = \"Testing tasks\"\ndescription = \"See how tasks in Loco are a simple linear workflow with access to your full a"
  },
  {
    "path": "docs-site/content/casts/006-mailers.md",
    "chars": 551,
    "preview": "+++\ntitle = \"Mailers\"\ndescription = \"Learn how to send emails from your app. As it turns out, emails are still an import"
  },
  {
    "path": "docs-site/content/casts/007-htmx.md",
    "chars": 594,
    "preview": "+++\ntitle = \"Full CRUD with HTMX scaffold generator\"\ndescription = \"Learn how to use HTMX with Loco. Using Loco's core g"
  },
  {
    "path": "docs-site/content/casts/_index.md",
    "chars": 123,
    "preview": "+++\ntitle = \"Loco Casts\"\ndescription =  \"Loco Casts\"\nsort_by = \"date\"\npaginate_by = 10\ntemplate = \"casts/section.html\"\n+"
  },
  {
    "path": "docs-site/content/docs/_index.md",
    "chars": 114,
    "preview": "+++\ntitle = \"Docs\"\ndescription = \"Docs for loco\"\nsort_by = \"weight\"\nweight = 1\ntemplate = \"docs/section.html\"\n+++\n"
  },
  {
    "path": "docs-site/content/docs/extras/_index.md",
    "chars": 117,
    "preview": "+++\ntitle = \"Extras\"\ndescription = \"\"\ntemplate = \"docs/section.html\"\nsort_by = \"weight\"\nweight = 5\ndraft = false\n+++\n"
  },
  {
    "path": "docs-site/content/docs/extras/authentication.md",
    "chars": 6992,
    "preview": "+++\ntitle = \"Authentication\"\ndescription = \"\"\ndate = 2021-05-01T18:20:00+00:00\nupdated = 2021-05-01T18:20:00+00:00\ndraft"
  },
  {
    "path": "docs-site/content/docs/extras/pluggability.md",
    "chars": 34418,
    "preview": "+++\ntitle = \"Pluggability\"\ndescription = \"\"\ndate = 2021-05-01T18:10:00+00:00\nupdated = 2021-05-01T18:10:00+00:00\ndraft ="
  },
  {
    "path": "docs-site/content/docs/extras/upgrades.md",
    "chars": 12319,
    "preview": "+++\ntitle = \"Upgrades\"\ndescription = \"\"\ndate = 2021-05-01T18:20:00+00:00\nupdated = 2021-05-01T18:20:00+00:00\ndraft = fal"
  },
  {
    "path": "docs-site/content/docs/extras/websocket.md",
    "chars": 435,
    "preview": "+++\ntitle = \"Websocket\"\ndescription = \"\"\ndate = 2024-01-21T18:20:00+00:00\nupdated = 2024-01-21T18:20:00+00:00\ndraft = fa"
  },
  {
    "path": "docs-site/content/docs/getting-started/_index.md",
    "chars": 126,
    "preview": "+++\ntitle = \"Getting Started\"\ndescription = \"\"\ntemplate = \"docs/section.html\"\nsort_by = \"weight\"\nweight = 1\ndraft = fals"
  },
  {
    "path": "docs-site/content/docs/getting-started/axum-users.md",
    "chars": 8394,
    "preview": "+++\ntitle = \"Axum vs Loco\"\ndescription = \"Shows how to move from Axum to Loco\"\ndate = 2023-12-01T19:30:00+00:00\nupdated "
  },
  {
    "path": "docs-site/content/docs/getting-started/guide.md",
    "chars": 29315,
    "preview": "+++\ntitle = \"The Loco Guide\"\ndate = 2021-05-01T08:00:00+00:00\nupdated = 2021-05-01T08:00:00+00:00\ndraft = false\nweight ="
  },
  {
    "path": "docs-site/content/docs/getting-started/starters.md",
    "chars": 4572,
    "preview": "+++\ntitle = \"Starters\"\ndate = 2021-12-19T08:00:00+00:00\nupdated = 2021-12-19T08:00:00+00:00\ndraft = false\nweight = 4\nsor"
  },
  {
    "path": "docs-site/content/docs/getting-started/tour/index.md",
    "chars": 8142,
    "preview": "+++\ntitle = \"A Quick Tour\"\ndate = 2021-05-01T08:00:00+00:00\nupdated = 2021-05-01T08:00:00+00:00\ndraft = false\nweight = 2"
  },
  {
    "path": "docs-site/content/docs/infrastructure/_index.md",
    "chars": 125,
    "preview": "+++\ntitle = \"Infrastructure\"\ndescription = \"\"\ntemplate = \"docs/section.html\"\nsort_by = \"weight\"\nweight = 4\ndraft = false"
  },
  {
    "path": "docs-site/content/docs/infrastructure/cache.md",
    "chars": 3154,
    "preview": "+++\ntitle = \"Cache\"\ndescription = \"\"\ndate = 2024-02-07T08:00:00+00:00\nupdated = 2025-04-22T08:00:00+00:00\ndraft = false\n"
  },
  {
    "path": "docs-site/content/docs/infrastructure/data.md",
    "chars": 3402,
    "preview": "+++\ntitle = \"Data\"\ndescription = \"\"\ndate = 2024-02-07T08:00:00+00:00\nupdated = 2024-02-07T08:00:00+00:00\ndraft = false\nw"
  },
  {
    "path": "docs-site/content/docs/infrastructure/deployment.md",
    "chars": 5806,
    "preview": "+++\ntitle = \"Deployment\"\ndate = 2021-05-01T08:00:00+00:00\nupdated = 2021-05-01T08:00:00+00:00\ndraft = false\nweight = 3\ns"
  },
  {
    "path": "docs-site/content/docs/infrastructure/storage.md",
    "chars": 7556,
    "preview": "+++\ntitle = \"Storage\"\ndescription = \"\"\ndate = 2024-02-07T08:00:00+00:00\nupdated = 2024-02-07T08:00:00+00:00\ndraft = fals"
  },
  {
    "path": "docs-site/content/docs/processing/_index.md",
    "chars": 121,
    "preview": "+++\ntitle = \"Processing\"\ndescription = \"\"\ntemplate = \"docs/section.html\"\nsort_by = \"weight\"\nweight = 3\ndraft = false\n+++"
  },
  {
    "path": "docs-site/content/docs/processing/mailers.md",
    "chars": 6510,
    "preview": "+++\ntitle = \"Mailers\"\ndescription = \"\"\ndate = 2021-05-01T18:10:00+00:00\nupdated = 2021-05-01T18:10:00+00:00\ndraft = fals"
  },
  {
    "path": "docs-site/content/docs/processing/scheduler.md",
    "chars": 9617,
    "preview": "+++\ntitle = \"Scheduler\"\ndescription = \"\"\ndate = 2024-11-09T18:10:00+00:00\nupdated = 2025-06-03T14:10:00+00:00\ndraft = fa"
  },
  {
    "path": "docs-site/content/docs/processing/task.md",
    "chars": 4180,
    "preview": "+++\ntitle = \"Tasks\"\ndescription = \"\"\ndate = 2021-05-01T18:10:00+00:00\nupdated = 2021-05-01T18:10:00+00:00\ndraft = false\n"
  },
  {
    "path": "docs-site/content/docs/processing/workers.md",
    "chars": 14264,
    "preview": "+++\ntitle = \"Workers\"\ndescription = \"\"\ndate = 2021-05-01T18:10:00+00:00\nupdated = 2021-05-01T18:10:00+00:00\ndraft = fals"
  },
  {
    "path": "docs-site/content/docs/resources/_index.md",
    "chars": 120,
    "preview": "+++\ntitle = \"Resources\"\ndescription = \"\"\ntemplate = \"docs/section.html\"\nsort_by = \"weight\"\nweight = 6\ndraft = false\n+++\n"
  },
  {
    "path": "docs-site/content/docs/resources/around-the-web.md",
    "chars": 1597,
    "preview": "+++\ntitle = \"Around the Web\"\ndescription = \"\"\ndate = 2024-01-21T19:00:00+00:00\nupdated = 2024-01-21T19:00:00+00:00\ndraft"
  },
  {
    "path": "docs-site/content/docs/resources/faq.md",
    "chars": 1991,
    "preview": "+++\ntitle = \"FAQ\"\ndescription = \"Answers to frequently asked questions.\"\ndate = 2021-05-01T19:30:00+00:00\nupdated = 2021"
  },
  {
    "path": "docs-site/content/docs/the-app/_index.md",
    "chars": 118,
    "preview": "+++\ntitle = \"The App\"\ndescription = \"\"\ntemplate = \"docs/section.html\"\nsort_by = \"weight\"\nweight = 2\ndraft = false\n+++\n"
  },
  {
    "path": "docs-site/content/docs/the-app/controller.md",
    "chars": 46230,
    "preview": "+++\ntitle = \"Controllers\"\ndescription = \"\"\ndate = 2021-05-01T18:10:00+00:00\nupdated = 2021-05-01T18:10:00+00:00\ndraft = "
  },
  {
    "path": "docs-site/content/docs/the-app/models.md",
    "chars": 36775,
    "preview": "+++\ntitle = \"Models\"\ndescription = \"\"\ndate = 2021-05-01T18:10:00+00:00\nupdated = 2024-01-07T21:10:00+00:00\ndraft = false"
  },
  {
    "path": "docs-site/content/docs/the-app/views.md",
    "chars": 13303,
    "preview": "+++\ntitle = \"Views\"\ndescription = \"\"\ndate = 2021-05-01T18:10:00+00:00\nupdated = 2021-05-01T18:10:00+00:00\ndraft = false\n"
  },
  {
    "path": "docs-site/content/docs/the-app/your-project.md",
    "chars": 13484,
    "preview": "+++\ntitle = \"Your Project\"\ndescription = \"\"\ndate = 2021-05-01T18:10:00+00:00\nupdated = 2024-01-07T21:10:00+00:00\ndraft ="
  },
  {
    "path": "docs-site/content/privacy-policy/_index.md",
    "chars": 689,
    "preview": "+++\ntitle = \"Privacy Policy\"\ndescription = \"We do not use cookies and we do not collect any personal data.\"\ndraft = fals"
  },
  {
    "path": "docs-site/package.json",
    "chars": 603,
    "preview": "{\n  \"name\": \"loco\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"build\": \"NODE_E"
  },
  {
    "path": "docs-site/static/ahrefs_f06cfb9c2671c1b7a5b6eec0d47a07719bd6d5a2240b829cad6a3f40684fa370",
    "chars": 89,
    "preview": "ahrefs-site-verification_f06cfb9c2671c1b7a5b6eec0d47a07719bd6d5a2240b829cad6a3f40684fa370"
  },
  {
    "path": "docs-site/static/js/main.js",
    "chars": 528,
    "preview": "// Set darkmode\ndocument.getElementById('mode').addEventListener('click', () => {\n\n    document.documentElement.classLis"
  },
  {
    "path": "docs-site/static/js/search.js",
    "chars": 10135,
    "preview": "var suggestions = document.getElementById('suggestions');\nvar userinput = document.getElementById('userinput');\n\ndocumen"
  },
  {
    "path": "docs-site/static/styles/styles.css",
    "chars": 50229,
    "preview": "/*\n! tailwindcss v3.4.7 | MIT License | https://tailwindcss.com\n*/\n\n/*\n1. Prevent padding and border from affecting elem"
  },
  {
    "path": "docs-site/static/syntax-theme-dark.css",
    "chars": 3331,
    "preview": "/*\n * theme \"OneHalfLight\" generated by syntect\n */\n\n.dark {\n  .z-code {\n  color: #dcdfe4;\n  background-color: #282c34;\n"
  },
  {
    "path": "docs-site/static/syntax-theme-light.css",
    "chars": 3097,
    "preview": "/*\n * theme \"OneHalfLight\" generated by syntect\n */\n\n.z-code {\n color: #383a42;\n background-color: #fafafa;\n border: 1px"
  },
  {
    "path": "docs-site/styles/styles.css",
    "chars": 5685,
    "preview": "@import \"tailwindcss/base\";\n@import \"tailwindcss/components\";\n@import \"tailwindcss/utilities\";\n@import \"tailwindcss/typo"
  },
  {
    "path": "docs-site/tailwind.config.js",
    "chars": 1549,
    "preview": "/** @type {import('tailwindcss').Config} */\n\nconst { fontFamily } = require(\"tailwindcss/defaultTheme\");\n\nmodule.exports"
  },
  {
    "path": "docs-site/templates/404.html",
    "chars": 993,
    "preview": "{% extends \"base.html\" %}\n\n{% block seo %}\n  {{ super() }} \n  {% set title = \"404 Page not found\" %}\n  \n  {% if config.t"
  },
  {
    "path": "docs-site/templates/base.html",
    "chars": 4593,
    "preview": "{% import 'macros/footer.html' as macros_footer -%}\n{% import 'macros/header.html' as macros_header -%}\n{% import 'macro"
  },
  {
    "path": "docs-site/templates/blog/atom.xml",
    "chars": 2034,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xml:lang=\"{{ lang }}\">\n    <title>{{ co"
  },
  {
    "path": "docs-site/templates/blog/page.html",
    "chars": 968,
    "preview": "{# Default page template used for blog contents #}\n\n{% extends \"page.html\" %}\n\n{% block body %}\n{% set page_class = \"blo"
  },
  {
    "path": "docs-site/templates/blog/rss.xml",
    "chars": 1736,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rss xmlns:atom=\"http://www.w3.org/2005/Atom\" version=\"2.0\">\n    <channel>\n      "
  },
  {
    "path": "docs-site/templates/blog/section.html",
    "chars": 2076,
    "preview": "{% extends \"section.html\" %}\n\n{% block body %}\n{% set page_class = \"blog list\" %}\n{% endblock body %}\n\n{% block header %"
  },
  {
    "path": "docs-site/templates/casts/page.html",
    "chars": 749,
    "preview": "{# Default page template used for blog contents #}\n\n{% extends \"page.html\" %}\n\n{% block body %}\n{% set page_class = \"cas"
  },
  {
    "path": "docs-site/templates/casts/section.html",
    "chars": 2212,
    "preview": "{% extends \"section.html\" %}\n\n{% block body %}\n{% set page_class = \"casts list\" %}\n{% endblock body %}\n\n{% block header "
  },
  {
    "path": "docs-site/templates/docs/page.html",
    "chars": 1594,
    "preview": "{% extends \"page.html\" %}\n\n{% block body %}\n{% set page_class = \"docs single\" %}\n{% endblock body %}\n\n{% block header %}"
  },
  {
    "path": "docs-site/templates/docs/section.html",
    "chars": 1670,
    "preview": "{% extends \"section.html\" %}\n\n{% block body %}\n{% set page_class = \"docs list\" %}\n{% endblock body %}\n\n{% block header %"
  },
  {
    "path": "docs-site/templates/index.html",
    "chars": 6645,
    "preview": "{% import 'macros/footer.html' as macros_footer -%}\n\n{% extends \"base.html\" %}\n\n{% block seo %}\n{{ super() }}\n\n{% if con"
  },
  {
    "path": "docs-site/templates/macros/docs-edit-page.html",
    "chars": 626,
    "preview": "{% macro docs_edit_page(current_path) %}\n<p class=\"edit-page\"><a\n        href=\"{{ config.extra.docs_repo }}/blob/{{ conf"
  },
  {
    "path": "docs-site/templates/macros/docs-navigation.html",
    "chars": 3434,
    "preview": "{% macro docs_navigation(page, current_section) %}\n<div class=\"flex items-center justify-between pt-8\">\n  {# Find lighte"
  },
  {
    "path": "docs-site/templates/macros/docs-sidebar.html",
    "chars": 1283,
    "preview": "{% macro docs_sidebar(current_section) %}\n<div>\n\t<nav class=\"flex gap-5 md:gap-10 flex-wrap py-8\" aria-label=\"Main navig"
  },
  {
    "path": "docs-site/templates/macros/docs-toc.html",
    "chars": 560,
    "preview": "{% macro docs_toc(page) %}\n{% if page.extra.toc %}\n<nav>\n\t<ul>\n\t\t{% for h1 in page.toc %}\n\t\t<li class=\"mb-1 px-2 py-1 te"
  },
  {
    "path": "docs-site/templates/macros/footer.html",
    "chars": 770,
    "preview": "{% macro footer() %}\n<div class=\"section bg-redrust dark:bg-zinc-800 pt-8\">\n  <div class=\"container flex flex-col items-"
  },
  {
    "path": "docs-site/templates/macros/header.html",
    "chars": 6699,
    "preview": "{% macro header(current_section) %}\n<header\n\tclass=\" sticky top-0 z-50 w-full border-border/40 backdrop-blur bg-backgrou"
  },
  {
    "path": "docs-site/templates/macros/javascript.html",
    "chars": 500,
    "preview": "{% macro javascript() %}\n<script type=\"text/javascript\" src=\"{{ get_url(path=\"js/main.js\") | safe }}\" defer></script>\n{%"
  },
  {
    "path": "docs-site/templates/macros/page-publish-metadata.html",
    "chars": 271,
    "preview": "{% macro page_publish_metadata(page) %}\n<div class=\"mb-8 text-sm text-gray-500\">\n    {{ page.date | date(format=config.e"
  },
  {
    "path": "docs-site/templates/macros/youtube.html",
    "chars": 507,
    "preview": "{% macro youtube(id, autoplay=false, class=false) %}\n  <div class=\"video-container\">\n    <iframe\n        src=\"https://ww"
  },
  {
    "path": "docs-site/templates/page.html",
    "chars": 1622,
    "preview": "{# Default page.html template #}\n\n{% extends \"base.html\" %}\n\n{% block seo %}\n{{ super() }}\n{% set title_addition = \"\" %}"
  },
  {
    "path": "docs-site/templates/section.html",
    "chars": 1292,
    "preview": "{# Default section.html template #}\n\n{% extends \"base.html\" %}\n\n{% block seo %}\n{{ super() }}\n{% set title_addition = \"\""
  },
  {
    "path": "docs-site/templates/shortcodes/get_env.html",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs-site/templates/taxonomy_list.html",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs-site/templates/taxonomy_single.html",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "docs-site/translations/tour-fr.md",
    "chars": 7369,
    "preview": "+++\ntitle = \"Aperçu rapide\"\ndate = 2021-05-01T08:00:00+00:00\nupdated = 2021-05-01T08:00:00+00:00\ndraft = false\nweight = "
  },
  {
    "path": "loco-cli/.gitignore",
    "chars": 45,
    "preview": "stateless-template\nsaas-template\n\nCargo.lock\n"
  },
  {
    "path": "loco-cli/.rustfmt.toml",
    "chars": 49,
    "preview": "max_width = 100\nuse_small_heuristics = \"Default\"\n"
  },
  {
    "path": "loco-cli/Cargo.toml",
    "chars": 414,
    "preview": "[workspace]\n\n[package]\nname = \"loco-cli\"\nversion = \"0.13.0\"\nedition = \"2021\"\ndescription = \"loco cli website generator\"\n"
  },
  {
    "path": "loco-cli/README.md",
    "chars": 2528,
    "preview": "# Loco CLI\n\nLoco CLI is a powerful command-line tool designed to streamline the process of generating Loco websites.\n\n##"
  },
  {
    "path": "loco-cli/src/bin/main.rs",
    "chars": 600,
    "preview": "fn main() {\n    println!(\"==============================================\");\n    println!(\"  ⚠️  DEPRECATION NOTICE: `loc"
  },
  {
    "path": "loco-cli/src/lib.rs",
    "chars": 1,
    "preview": "\n"
  },
  {
    "path": "loco-gen/.gitattributes",
    "chars": 28,
    "preview": "src/templates/* text eol=lf\n"
  },
  {
    "path": "loco-gen/Cargo.toml",
    "chars": 923,
    "preview": "[package]\nname = \"loco-gen\"\nversion = \"0.16.4\"\ndescription = \"Loco generators\"\nlicense.workspace = true\nedition.workspac"
  },
  {
    "path": "loco-gen/src/controller.rs",
    "chars": 1649,
    "preview": "use super::{AppInfo, GenerateResults, Result};\nuse crate as gen;\nuse rrgen::RRgen;\nuse serde_json::json;\nuse std::path::"
  },
  {
    "path": "loco-gen/src/infer.rs",
    "chars": 6778,
    "preview": "use cruet::{case::snake::to_snake_case, Inflector};\n\nuse crate::{Error, Result};\n\n#[derive(Debug, PartialEq, Eq)]\npub en"
  },
  {
    "path": "loco-gen/src/lib.rs",
    "chars": 21661,
    "preview": "// this is because not using with-db renders some of the structs below unused\n// TODO: should be more properly aligned w"
  },
  {
    "path": "loco-gen/src/mappings.json",
    "chars": 9762,
    "preview": "{\n  \"field_types\": [\n    {\n      \"name\": \"uuid^\",\n      \"rust\": \"Uuid\",\n      \"schema\": \"uuid_uniq\",\n      \"col_type\": \""
  },
  {
    "path": "loco-gen/src/migration.rs",
    "chars": 3131,
    "preview": "use std::path::Path;\n\nuse chrono::Utc;\nuse rrgen::RRgen;\nuse serde_json::json;\n\nuse crate::{\n    infer, model::get_colum"
  },
  {
    "path": "loco-gen/src/model.rs",
    "chars": 9163,
    "preview": "use std::{collections::HashMap, env::current_dir, path::Path};\n\nuse chrono::Utc;\nuse duct::cmd;\nuse heck::ToUpperCamelCa"
  },
  {
    "path": "loco-gen/src/scaffold.rs",
    "chars": 3840,
    "preview": "use std::path::Path;\n\nuse rrgen::RRgen;\nuse serde_json::json;\n\nuse crate::{\n    get_mappings, infer::parse_field_type, m"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array!_big_int].snap",
    "chars": 2209,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array!_bool].snap",
    "chars": 522,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array!_double].snap",
    "chars": 4529,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array!_float].snap",
    "chars": 2413,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array!_int].snap",
    "chars": 2137,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array!_string].snap",
    "chars": 1937,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array^_big_int].snap",
    "chars": 2209,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array^_bool].snap",
    "chars": 522,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array^_double].snap",
    "chars": 4529,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array^_float].snap",
    "chars": 2413,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array^_int].snap",
    "chars": 2137,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array^_string].snap",
    "chars": 1937,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array_big_int].snap",
    "chars": 2158,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array_bool].snap",
    "chars": 520,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array_double].snap",
    "chars": 4478,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array_float].snap",
    "chars": 2362,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array_int].snap",
    "chars": 2086,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_array_string].snap",
    "chars": 1890,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_big_int!_big_int!].snap",
    "chars": 1031,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_big_int^_big_int^].snap",
    "chars": 1031,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_big_int_big_int].snap",
    "chars": 1008,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_big_unsigned!_big_unsigned!].snap",
    "chars": 1066,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_big_unsigned^_big_unsigned^].snap",
    "chars": 1066,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_big_unsigned_big_unsigned].snap",
    "chars": 1043,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_binary_len!_binary_len!].snap",
    "chars": 1208,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_binary_len^_binary_len^].snap",
    "chars": 1208,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_binary_len_binary_len].snap",
    "chars": 1185,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_blob!_blob!].snap",
    "chars": 1166,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_blob^_blob^].snap",
    "chars": 1166,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_blob_blob].snap",
    "chars": 1143,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_bool!_bool!].snap",
    "chars": 880,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_bool_bool].snap",
    "chars": 857,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_date!_date!].snap",
    "chars": 882,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_date^_date^].snap",
    "chars": 882,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_date_date].snap",
    "chars": 859,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_date_time!_date_time!].snap",
    "chars": 937,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_date_time^_date_time^].snap",
    "chars": 937,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_date_time_date_time].snap",
    "chars": 914,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_decimal!_decimal!].snap",
    "chars": 1075,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_decimal^_decimal^].snap",
    "chars": 1075,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_decimal].snap",
    "chars": 1052,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_len!_decimal_len!].snap",
    "chars": 1103,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_len^_decimal_len^].snap",
    "chars": 1103,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_decimal_len_decimal_len].snap",
    "chars": 1080,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_double!_double!].snap",
    "chars": 2188,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_double^_double^].snap",
    "chars": 2188,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_double_double].snap",
    "chars": 2165,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_float!_float!].snap",
    "chars": 1101,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_float^_float^].snap",
    "chars": 1101,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_float_float].snap",
    "chars": 1078,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_int!_int!].snap",
    "chars": 967,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_int^_int^].snap",
    "chars": 967,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_int_int].snap",
    "chars": 944,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_json!_json!].snap",
    "chars": 928,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_json_json].snap",
    "chars": 905,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_jsonb!_jsonb!].snap",
    "chars": 935,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_jsonb^_jsonb^].snap",
    "chars": 935,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_jsonb_jsonb].snap",
    "chars": 912,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_money!_money!].snap",
    "chars": 1061,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_money^_money^].snap",
    "chars": 1061,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_money_money].snap",
    "chars": 1038,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_small_int!_small_int!].snap",
    "chars": 989,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_small_int^_small_int^].snap",
    "chars": 989,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_small_int_small_int].snap",
    "chars": 966,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_small_unsigned!_small_unsigned!].snap",
    "chars": 1024,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  },
  {
    "path": "loco-gen/src/snapshots/loco_gen__tera_ext__tests__can_render_form_field_[form_small_unsigned^_small_unsigned^].snap",
    "chars": 1024,
    "preview": "---\nsource: loco-gen/src/tera_ext.rs\nexpression: \"format!(\\\"Create form\\\\n\\\\n{create_form}\\\\n\\\\nEdit Form\\\\n\\\\n{edit_for"
  }
]

// ... and 594 more files (download for full content)

About this extraction

This page contains the full source code of the loco-rs/loco GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 794 files (2.4 MB), approximately 680.2k tokens, and a symbol index with 2070 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!