entrypoint

Crates.ioentrypoint
lib.rsentrypoint
version0.2.0
sourcesrc
created_at2023-09-20 17:40:08.719204
updated_at2024-02-22 13:01:01.201264
descriptionopinionated application framework/wrapper that eliminates main function boilerplate
homepagehttps://github.com/melloyawn/entrypoint
repositoryhttps://github.com/melloyawn/entrypoint
max_upload_size
id978379
size59,714
Corey Cothrum (coreycothrum)

documentation

README

entrypoint

Crates.io Crates.io Documentation License

eliminate main function boilerplate with this opinionated application framework/wrapper

About

entrypoint has the following design goals:

  • eliminate application startup/configuration boilerplate
  • help enforce application best practices

What does this crate actually do?

entrypoint wraps a user defined function with automatic configuration/setup/processing of:

  • easy application error handling (via anyhow)
  • command-line argument parsing (via clap)
  • .dotenv file processing and environment variable population/overrides (via dotenvy)
  • logging (via tracing)

The user defined function is intended to be/replace main().

Meaning, this main/entrypoint function can be written as if all the configuration/processing/boilerplate is ready-to-use. More explicitly:

  • anyhow is available and ready to use
  • clap::Parser struct has been parsed and populated
  • .dotenv files have been parsed; environment variables are ready to go
  • tracing has been configured and the global subscriber has been registered

A note from the developer

entrypoint was as much about deploying my first crate as anything else.

Turns out, it's really not that useful. I kind of think it's better just to explicitly set this stuff up in your application. The juice isn't work the squeeze.

It's unlikely further development will occur.

Usage

Default Config

  1. Include the entrypoint prelude:

    use entrypoint::prelude::*;
    
  2. Define a clap struct and derive default entrypoint trait impls:

    #[derive(clap::Parser, DotEnvDefault, LoggerDefault, Debug)]
    #[log_format(full)]
    #[log_level(entrypoint::tracing::Level::INFO)]
    #[command(version, about, long_about = None)]
    struct CLIArgs {
        #[arg(short, long, env)]
        cli_arg: bool,
    }
    
  3. Define an entrypoint/main function:

    #[entrypoint::entrypoint]
    fn entrypoint(args: CLIArgs) -> entrypoint::anyhow::Result<()> {
        // args are parsed and ready to use
        info!("cli_arg set to: {:?}", args.cli_arg);
    
        // env::vars() already loaded-from/merged-with .dotenv file(s)
        let _my_var = env::vars("SOMETHING_FROM_DOTENV_FILE");
    
        // logging is ready to use
        info!("entrypoint::entrypoint");
    
        Ok(())
    }
    

Custom Config

Using the default behavior is totally reasonable, but overwriting some default impl(s) can provide customization.

Usage Notes

  1. The entrypoint function must:
    1. Have a clap::Parser input parameter
    2. return entrypoint::anyhow::Result<()>
  2. #[entrypoint::entrypoint] ordering may matter when used with other attribute macros (e.g. [tokio::main]).

Documentation

For more information, refer to:

Crates

entrypoint is divided into the following crates:

Contributing

Before doing anything else: open an issue.

Commit count: 46

cargo fmt