Trait Project

Source
pub trait Project {
    // Provided methods
    fn cli_metadata(&self) -> CliMetadata { ... }
    fn config(&self, config_name: &str) -> Result<ProjectConfig> { ... }
    fn register_tasks(&self, cli: &mut Cli) { ... }
    fn register_apps(
        &self,
        apps: &mut AppBuilder,
        context: &ProjectContext<WithConfig>,
    ) { ... }
    fn auth_backend(
        &self,
        context: &ProjectContext<WithApps>,
    ) -> Box<dyn AuthBackend> { ... }
    fn middlewares(
        &self,
        handler: RootHandlerBuilder,
        context: &ProjectContext<WithApps>,
    ) -> BoxedHandler { ... }
    fn server_error_handler(&self) -> Box<dyn ErrorPageHandler> { ... }
    fn not_found_handler(&self) -> Box<dyn ErrorPageHandler> { ... }
}
Expand description

The main trait for a Cot project.

This is the main entry point for your application. This trait defines the configuration, apps, and other project-wide resources.

It’s mainly meant to be used with the cot::main attribute macro.

§Examples

use cot::cli::CliMetadata;
use cot::Project;

struct MyProject;
impl Project for MyProject {
    fn cli_metadata(&self) -> CliMetadata {
        cot::cli::metadata!()
    }
}

#[cot::main]
fn main() -> impl Project {
    MyProject
}

Provided Methods§

Source

fn cli_metadata(&self) -> CliMetadata

Returns the metadata for the CLI.

This method is used to set the name, version, authors, and description of the CLI application. This is meant to be typically used with cli::metadata!() which automatically retrieves this data from the crate metadata.

The default implementation sets the name, version, authors, and description of the cot crate.

§Examples
use cot::cli::CliMetadata;
use cot::Project;

struct HelloProject;
impl Project for HelloProject {
    fn cli_metadata(&self) -> CliMetadata {
        cot::cli::metadata!()
    }
}
Source

fn config(&self, config_name: &str) -> Result<ProjectConfig>

Returns the configuration for the project.

The default implementation reads the configuration from the config directory in the current working directory (for instance, if config_name is test, then config/test.toml in the current working directory is read). If the file does not exist, it tries to read the file directly at config_name path.

You might want to override this method if you want to read the configuration from a different source, or if you want to hardcode it in the binary.

§Errors

This method may return an error if it cannot read or parse the configuration.

§Examples
use cot::config::ProjectConfig;
use cot::Project;

struct MyProject;
impl Project for MyProject {
    fn config(&self, config_name: &str) -> cot::Result<ProjectConfig> {
        Ok(ProjectConfig::default())
    }
}
Source

fn register_tasks(&self, cli: &mut Cli)

Adds a task to the CLI.

This method is used to add a task to the CLI. The task will be available as a subcommand of the main CLI command.

§Examples
use async_trait::async_trait;
use clap::{ArgMatches, Command};
use cot::cli::{Cli, CliTask};
use cot::project::WithConfig;
use cot::{Bootstrapper, Project};

struct Frobnicate;

#[async_trait(?Send)]
impl CliTask for Frobnicate {
    fn subcommand(&self) -> Command {
        Command::new("frobnicate")
    }

    async fn execute(
        &mut self,
        _matches: &ArgMatches,
        _bootstrapper: Bootstrapper<WithConfig>,
    ) -> cot::Result<()> {
        println!("Frobnicating...");

        Ok(())
    }
}

struct MyProject;
impl Project for MyProject {
    fn register_tasks(&self, cli: &mut Cli) {
        cli.add_task(Frobnicate)
    }
}
Source

fn register_apps( &self, apps: &mut AppBuilder, context: &ProjectContext<WithConfig>, )

Registers the apps for the project.

§Examples
use cot::project::{AppBuilder, WithConfig};
use cot::{App, Project, ProjectContext};

struct MyApp;
impl App for MyApp {
    fn name(&self) -> &str {
        "my_app"
    }
}

struct MyProject;
impl Project for MyProject {
    fn register_apps(&self, apps: &mut AppBuilder, context: &ProjectContext<WithConfig>) {
        apps.register(MyApp);
    }
}
Source

fn auth_backend( &self, context: &ProjectContext<WithApps>, ) -> Box<dyn AuthBackend>

Sets the authentication backend to use.

Note that it’s typically not necessary to override this method, as it already provides a default implementation that uses the auth backend specified in the project’s configuration.

§Examples
use cot::auth::{AuthBackend, NoAuthBackend};
use cot::project::WithApps;
use cot::{App, Project, ProjectContext};

struct HelloProject;
impl Project for HelloProject {
    fn auth_backend(&self, context: &ProjectContext<WithApps>) -> Box<dyn AuthBackend> {
        Box::new(NoAuthBackend)
    }
}
Source

fn middlewares( &self, handler: RootHandlerBuilder, context: &ProjectContext<WithApps>, ) -> BoxedHandler

Returns the middlewares for the project.

This method is used to return the middlewares for the project. The middlewares will be applied to all routes in the project.

§Examples
use cot::middleware::LiveReloadMiddleware;
use cot::project::{RootHandlerBuilder, WithApps};
use cot::{BoxedHandler, Project, ProjectContext};

struct MyProject;
impl Project for MyProject {
    fn middlewares(
        &self,
        handler: RootHandlerBuilder,
        context: &ProjectContext<WithApps>,
    ) -> BoxedHandler {
        handler
            .middleware(LiveReloadMiddleware::from_context(context))
            .build()
    }
}
Source

fn server_error_handler(&self) -> Box<dyn ErrorPageHandler>

Returns the 500 Internal Server Error handler for the project.

The default handler returns a simple, static page.

§Errors

This method may return an error if the handler fails to build a response. In this case, the error will be logged and a generic error page will be returned to the user.

§Panics

Note that this handler is exempt of the typical panic handling machinery in Cot. This means that if this handler panics, no response will be sent to a user. Because of that, you should avoid panicking here and return Err instead.

§Examples
use cot::project::ErrorPageHandler;
use cot::response::{Response, ResponseExt};
use cot::{Body, Project, StatusCode};

struct MyProject;
impl Project for MyProject {
    fn server_error_handler(&self) -> Box<dyn ErrorPageHandler> {
        Box::new(MyHandler)
    }
}

struct MyHandler;
impl ErrorPageHandler for MyHandler {
    fn handle(&self) -> cot::Result<Response> {
        Ok(Response::new_html(
            StatusCode::INTERNAL_SERVER_ERROR,
            Body::fixed("Internal Server Error"),
        ))
    }
}
Source

fn not_found_handler(&self) -> Box<dyn ErrorPageHandler>

Returns the 404 Not Found handler for the project.

The default handler returns a simple, static page.

§Errors

This method may return an error if the handler fails to build a response. In this case, the error will be logged and a generic error page will be returned to the user.

§Panics

Note that this handler is exempt of the typical panic handling machinery in Cot. This means that if this handler panics, no response will be sent to a user. Because of that, you should avoid panicking here and return Err instead.

§Examples
use cot::project::ErrorPageHandler;
use cot::response::{Response, ResponseExt};
use cot::{Body, Project, StatusCode};

struct MyProject;
impl Project for MyProject {
    fn not_found_handler(&self) -> Box<dyn ErrorPageHandler> {
        Box::new(MyHandler)
    }
}

struct MyHandler;
impl ErrorPageHandler for MyHandler {
    fn handle(&self) -> cot::Result<Response> {
        Ok(Response::new_html(
            StatusCode::NOT_FOUND,
            Body::fixed("Not Found"),
        ))
    }
}

Implementors§