ayun_console/
service.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use crate::{command::Command, commands, Console};
use ayun_config::config;
use ayun_core::{
    traits::{ApplicationTrait, ErrorTrait, ServiceTrait},
    Error, Result,
};

impl ServiceTrait for Console {
    type Item = Command;

    fn new() -> Self {
        Self::default()
    }

    fn register(mut self, command: Self::Item) -> Self {
        self.commands
            .insert(command.name().to_string(), command.command().clone());
        self.closures
            .insert(command.name().to_string(), command.handler().clone());

        self
    }

    fn init<A: ApplicationTrait>() -> Self {
        let mut console = (&A::with_console() as &dyn std::any::Any)
            .downcast_ref::<Self>()
            .cloned()
            .unwrap_or(Self::default());

        #[cfg(feature = "command-make")]
        {
            console = console.register(Command::new::<A, commands::Make>());
        }

        #[cfg(feature = "command-migrate")]
        {
            console = console.register(Command::new::<A, commands::Migrate>());
        }

        #[cfg(feature = "command-server")]
        {
            console = console.register(Command::new::<A, commands::Server>());
        }

        #[cfg(feature = "command-schedule")]
        {
            console = console.register(Command::new::<A, commands::Schedule>());
        }

        #[cfg(feature = "command-status")]
        {
            console = console.register(Command::new::<A, commands::Status>());
        }

        console = console.register(Command::new::<A, commands::Publish>());

        console
    }

    fn run(self) -> Result<(), Error> {
        let environment = config::<config::App>("app")
            .map_err(Error::wrap)?
            .environment;

        let span = tracing::debug_span!("console",environment=%environment);
        let _enter = span.enter();

        let commands = self.inner.subcommands(self.commands.values());

        match commands.clone().get_matches().subcommand() {
            Some((name, arg_matches)) => {
                if let Some(closure) = self.closures.get(name) {
                    if let Some(err) = closure(arg_matches.to_owned()).err() {
                        tracing::error!("[command] `{}` handle error: {}", name, err);
                    }
                }
            }
            None => commands.clone().print_help()?,
        }

        Ok(())
    }
}