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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use crate::{ops::forc_postgres_createdb, pg::PostgresVersion, utils::db_dir_or_default};
use anyhow::Result;
use clap::Parser;
use fuel_indexer_lib::defaults;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

/// Create a new database.
#[derive(Debug, Parser, Clone, Serialize, Deserialize)]
pub struct Command {
    /// Name of database.
    #[clap(help = "Name of database.")]
    pub name: String,

    /// Database user.
    #[clap(short, long, default_value = defaults::POSTGRES_USER, help = "Database user.")]
    pub user: String,

    /// Database password.
    #[clap(short, long, default_value = defaults::POSTGRES_PASSWORD, help = "Database password.")]
    pub password: String,

    /// Port to use.
    #[clap(short, long, default_value = defaults::POSTGRES_PORT, help = "Port to use.")]
    pub port: String,

    /// Where to store the PostgreSQL database.
    #[clap(long, help = "Where to store the PostgreSQL database.")]
    pub database_dir: Option<PathBuf>,

    /// Authentication method.
    #[clap(long, default_value = "plain", value_parser(["plain", "md5", "scram-sha-256"]), help = "Authentication method.")]
    pub auth_method: String,

    /// Do not clean up files and directories on database drop.
    #[clap(long, help = "Do not clean up files and directories on database drop.")]
    pub persistent: bool,

    /// Duration to wait before terminating process execution for pg_ctl start/stop and initdb.
    #[clap(
        long,
        help = "Duration to wait before terminating process execution for pg_ctl start/stop and initdb."
    )]
    pub timeout: Option<u64>,

    /// The directory containing migration scripts.
    #[clap(long, help = "The directory containing migration scripts.")]
    pub migration_dir: Option<PathBuf>,

    /// PostgreSQL version to use.
    #[clap(
        long,
        arg_enum,
        default_value = "v14",
        help = "PostgreSQL version to use."
    )]
    pub postgres_version: PostgresVersion,

    /// Start the PostgreSQL instance after creation.
    #[clap(long, help = "Start the PostgreSQL instance after creation.")]
    pub start: bool,

    /// Fuel indexer configuration file.
    #[clap(short, long, help = "Fuel indexer configuration file.")]
    pub config: Option<PathBuf>,
}

impl Default for Command {
    fn default() -> Self {
        Command {
            name: defaults::POSTGRES_DATABASE.to_string(),
            password: defaults::POSTGRES_PASSWORD.to_string(),
            user: defaults::POSTGRES_USER.to_string(),
            port: defaults::POSTGRES_PORT.to_string(),
            database_dir: None,
            auth_method: "plain".to_string(),
            persistent: true,
            start: false,
            config: None,
            timeout: None,
            migration_dir: None,
            postgres_version: PostgresVersion::V14,
        }
    }
}

pub async fn exec(command: Box<Command>) -> Result<()> {
    let Command {
        name,
        user,
        password,
        port,
        database_dir,
        auth_method,
        persistent,
        timeout,
        migration_dir,
        postgres_version,
        start,
        config,
    } = *command;

    let database_dir = db_dir_or_default(database_dir.as_ref(), &name);

    forc_postgres_createdb::init(Command {
        name,
        user,
        password,
        port,
        database_dir: Some(database_dir),
        auth_method,
        persistent,
        timeout,
        migration_dir,
        postgres_version,
        start,
        config,
    })
    .await?;
    Ok(())
}