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: &RegisterAppsContext,
) { ... }
fn auth_backend(&self, context: &AuthBackendContext) -> Arc<dyn AuthBackend> { ... }
fn middlewares(
&self,
handler: RootHandlerBuilder,
context: &MiddlewareContext,
) -> RootHandler { ... }
fn error_handler(&self) -> DynErrorPageHandler { ... }
}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::Project;
use cot::cli::CliMetadata;
struct MyProject;
impl Project for MyProject {
fn cli_metadata(&self) -> CliMetadata {
cot::cli::metadata!()
}
}
#[cot::main]
fn main() -> impl Project {
MyProject
}Provided Methods§
Sourcefn cli_metadata(&self) -> CliMetadata
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::Project;
use cot::cli::CliMetadata;
struct HelloProject;
impl Project for HelloProject {
fn cli_metadata(&self) -> CliMetadata {
cot::cli::metadata!()
}
}Sourcefn config(&self, config_name: &str) -> Result<ProjectConfig>
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::Project;
use cot::config::ProjectConfig;
struct MyProject;
impl Project for MyProject {
fn config(&self, config_name: &str) -> cot::Result<ProjectConfig> {
Ok(ProjectConfig::default())
}
}Sourcefn register_tasks(&self, cli: &mut Cli)
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)
}
}Sourcefn register_apps(&self, apps: &mut AppBuilder, context: &RegisterAppsContext)
fn register_apps(&self, apps: &mut AppBuilder, context: &RegisterAppsContext)
Registers the apps for the project.
§Examples
use cot::project::{AppBuilder, RegisterAppsContext};
use cot::{App, Project};
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: &RegisterAppsContext) {
apps.register(MyApp);
}
}Sourcefn auth_backend(&self, context: &AuthBackendContext) -> Arc<dyn AuthBackend>
fn auth_backend(&self, context: &AuthBackendContext) -> Arc<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 std::sync::Arc;
use cot::auth::{AuthBackend, NoAuthBackend};
use cot::project::AuthBackendContext;
use cot::{App, Project};
struct HelloProject;
impl Project for HelloProject {
fn auth_backend(&self, context: &AuthBackendContext) -> Arc<dyn AuthBackend> {
Arc::new(NoAuthBackend)
}
}Sourcefn middlewares(
&self,
handler: RootHandlerBuilder,
context: &MiddlewareContext,
) -> RootHandler
fn middlewares( &self, handler: RootHandlerBuilder, context: &MiddlewareContext, ) -> RootHandler
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::Project;
use cot::middleware::LiveReloadMiddleware;
use cot::project::{MiddlewareContext, RootHandler, RootHandlerBuilder};
struct MyProject;
impl Project for MyProject {
fn middlewares(
&self,
handler: RootHandlerBuilder,
context: &MiddlewareContext,
) -> RootHandler {
handler
.middleware(LiveReloadMiddleware::from_context(context))
.build()
}
}Sourcefn error_handler(&self) -> DynErrorPageHandler
fn error_handler(&self) -> DynErrorPageHandler
Returns the error handler for the project.
The default handler returns a simple, minimalistic error page that displays the status code canonical name and a generic error message.
§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. Because of that, you should avoid returning an error from this handler and try to handle the error gracefully instead.
§Panics
Note that this handler is exempt from 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;
use cot::error::handler::{DynErrorPageHandler, RequestError};
use cot::html::Html;
use cot::response::IntoResponse;
struct MyProject;
impl Project for MyProject {
fn error_handler(&self) -> DynErrorPageHandler {
DynErrorPageHandler::new(error_handler)
}
}
async fn error_handler(error: RequestError) -> impl IntoResponse {
Html::new(format!("An error occurred: {error}")).with_status(error.status_code())
}