Skip to content

Latest commit

 

History

History
682 lines (539 loc) · 36.7 KB

CHANGELOG.md

File metadata and controls

682 lines (539 loc) · 36.7 KB

Changelog

Unreleased

v0.13.0

  • Added SQLite background job support #969
  • Added automatic updating of updated_at on change #962
  • fixed codegen injection point in migrations #952

NOTE: update your migration listing module like so:

// 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 #955:
$ generate scaffold posts title:string! content:string! written_by:references:users approved_by:references:users
  • Added hot-reload like experience to Tera templates #977, in debug builds only.

NOTE: update your initializers after_routes like so:

// 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. #931
  • Use a single loco-rs dep for a whole project. #927
  • chore: fix generated testcase. #939
  • chore: Correct cargo test message. #938
  • Add relevant meta tags for better defaults. #943
  • Update cli message with correct command. #942
  • remove lazy_static. #941
  • change update HTTP verb semantics to put+patch. #919
  • Fixed HTML scaffold error. #960
  • Scaffolded HTML update method should be POST. #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) #818

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

Routes::new()
    .prefix("api/notes")
    .add("/", get(list))
  • starters: removed .devcontainer which can now be found in 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 #896

  • cleanup: loco-extras was moved out of the repo, but we've incorporated MultiDB and ExtraDB from extras into loco-rs #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:

    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 #851
  • Add good pragmas to Sqlite #848
  • Upgrade to rsbuild 1.0. #792
  • Implements fmt::Debug to pub structs. #812
  • Add num_workers config for sidekiq queue. #823
  • Fix some comments in the starters and example code. #824
  • Fix Y2038 bug for JWT on 32 bit platforms. #825
  • Make App URL in Boot Banner Clickable. #826
  • Add --no-banner flag to allow disabling the banner display. #839
  • add on_shutdown hook. #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. #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
  • 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:
// 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:

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:
// 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:

# update
validator = { version = "0.18" }
  • UPGRADED (BREAKING): axum-test crate was upgraded Update your Cargo.toml to version 16:
# update
axum-test = { version = "16" }

v0.9.0

  • Add fallback behavior. #732
  • Add Scheduler Feature for Running Cron Jobs. #735
  • Add --html, --htmx and --api flags to scaffold CLI command. #749
  • Add base template for scaffold generation. #752
  • Connect Redis only when the worker is BackgroundQueue. #755
  • Add loco doctor --config. #736
  • Rename demo: blo -> demo_app. #741

v0.8.1

  • fix: introduce secondary binary for compile-and-run on Windows. #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 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). 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. #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<()>
    ```
    
    1. Modify examples/playground.rs You need to apply two changes here:

      a. Update the Function Signature Before:

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

      After:

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

      b. Adjust the Context Handling Before:

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

      After:

      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. #650

  • Bump serial_test crate to 3.1.1. #651

  • Bumo object store to create to 0.10.2. #654

  • Bump axum crate to 0.7.5. #652

  • Add Hooks::before_routes to give user control over initial axum::Router construction. #646

  • Support logger file appender. #636

  • Response from the template. #682

  • Add get_or_insert function to cache layer. #637

  • Bump ORM create to 1.0.0. #684

0.6.2

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

0.6.1

  • Upgrade htmx generator to htmx2. #629

0.6.0 #610

  • Bump socketioxide to v0.13.1. #594
  • Add CC and BCC fields to the mailers. #599
  • Delete reset tokens after use. #602
  • Generator html support delete entity. #604
  • Breaking changes move task args from BTreeMap to struct. #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. #611
  • Update shuttle version in deployment generation. #616

v0.5.0 #593

  • refactor auth middleware for supporting bearer, cookie and query. #560
  • SeaORM upgraded: rc1 -> rc4. #585
  • Adding Cache to app content. #570
  • Apply a layer to a specific handler using layer method. #554
  • Add the debug macro to the templates to improve the errors. #547
  • Opentelemetry initializer. #531
  • Refactor auth middleware for supporting bearer, cookie and query #560
  • Add redirect response #563
  • Breaking changes Adding a custom claims Option<serde_json::Value> to the UserClaims struct (type changed). #578
  • Breaking changes Refactored DSL and Pagination: namespace changes. #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.
  • 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. #590
# 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. #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:
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 #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. #507

  • Added: in your configuration you can now use an initializers: section for initializer specific settings

    # 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. #506

  • Let Result accept other errors. #505

  • Allow trailing slashes in URIs by adding the NormalizePathLayer. #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:

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. #463
  • Wrap seaorm query and condition for common use cases. #463
  • Adding to loco-extras initializer for extra or multiple db. #471
  • Scaffold now supporting different templates such as API,HTML or htmx, this future is in beta.#474
  • Fix generatore fields types + adding tests. #459
  • Fix channel cors. #430
  • Improve auth controller compatibility with frontend #472

0.3.1

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

0.2.3

v0.2.2

  • fix: public fields in mailer-op. e51b7e
  • fix: handle missing db permissions. e51b7e

v0.2.1

  • enable compression for CompressionLayer, not etag. #356
  • Fix nullable JSONB column schema definition. #357

v0.2.0

  • Add: Loco now has Initializers (see the docs). 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. #343
  • Init logger in cli.rs. #338
  • Add: return JSON schema in panic HTTP layer. #336
  • Add: JSON field support in model generation. #327 #332
  • Add: float support in model generation. #317
  • Fix: conflicting idx definition on M:M migration. #311
  • Add: Breaking changes Supply AppContext to routes Hook. Migration steps in src/app.rs:
// 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
// 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:
format::render()
    .cookies(&[
        cookie::Cookie::new("foo", "bar"),
        cookie::Cookie::new("baz", "qux"),
    ])?
    .etag("foobar")?
    .json(notes)

v0.1.9

middlewares:
  compression:
    enable: true
  • Create a new Database from the CLI. #223
  • Validate if seaorm CLI is installed before running cargo loco db entities and show a better error to the user. #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. #215
  • Adding the app name and the environment to the DB name when creating a new starter. #216
  • Fix generator when users adding a created_at or update_at fields. #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:
#...
  middlewares:
    etag:
      enable: true

usage:

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

Authentication: Added API Token Authentication!

  • See #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:

#[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:

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:

    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 #170
  • Braking changes: Adding Hooks::boot application. Migration steps:
    // 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 #41
  • adding tests for note requests #156
  • Define the min rust version the loco can run #164
  • Added cargo loco doctor cli command for validate and diagnose configurations. #145
  • Added ability to specify settings: in config files, which are available in context
  • Adding compilation mode in the banner. #127
  • Support shuttle deployment generator. #124
  • Adding a static asset middleware which allows to serve static folder/data. Enable this section in config. #134
     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. #133
  • Improve docker deployment generator. #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 templates in config YAML files

Example of pulling a port from environment:

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 #110

  • Configure Cors middleware #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. #114

  • Adding docker deployment generator #119

DOCS:

  • Remove duplicated docs in auth section
  • FAQ docs: #116

ENHANCEMENTS:

  • Remove unused libs: #106
  • turn off default features in tokio #118

0.1.5

NEW FEATURES

  • format:html #74
  • Create a stateless HTML starter #100
  • Added worker generator + adding a way to test workers #92

ENHANCEMENTS:

  • CI: allows cargo cli run on fork prs #96