initial project setup
This commit is contained in:
commit
75b57539d9
1
.dockerignore
Normal file
1
.dockerignore
Normal file
|
@ -0,0 +1 @@
|
|||
**/target
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
|
||||
*.pw
|
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"cSpell.words": [
|
||||
"sqlx"
|
||||
]
|
||||
}
|
2234
Cargo.lock
generated
Normal file
2234
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
30
Cargo.toml
Normal file
30
Cargo.toml
Normal file
|
@ -0,0 +1,30 @@
|
|||
[package]
|
||||
name = "kalkulog-server"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
name = "kalkulog-server"
|
||||
path = "src/main.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
sea-orm-migration = "0.11.3"
|
||||
thiserror = "1.0.40"
|
||||
|
||||
[dependencies.derive_builder]
|
||||
version = "0.12.0"
|
||||
features = ["clippy"]
|
||||
|
||||
[dependencies.tokio]
|
||||
version = "1.28.1"
|
||||
features = ["full"]
|
||||
|
||||
[dependencies.sea-orm]
|
||||
version = "^0"
|
||||
features = [
|
||||
"sqlx-postgres",
|
||||
"runtime-tokio-rustls",
|
||||
"macros",
|
||||
"with-time"
|
||||
]
|
11
Dockerfile
Normal file
11
Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
|||
FROM rustlang/rust:nightly-bullseye-slim
|
||||
WORKDIR /src
|
||||
ADD Cargo.toml Cargo.lock /src/
|
||||
RUN echo "fn main() {}" > dummy.rs &&\
|
||||
sed -i "s:src/main.rs:dummy.rs:" Cargo.toml
|
||||
RUN cargo build --release
|
||||
ADD src/ src/
|
||||
RUN rm dummy.rs &&\
|
||||
sed -i "s:dummy.rs:src/main.rs:" Cargo.toml
|
||||
RUN cargo build --release
|
||||
CMD ["target/release/kalkulog-server"]
|
60
src/db/mod.rs
Normal file
60
src/db/mod.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
use std::{
|
||||
default::default,
|
||||
env,
|
||||
ffi::{OsStr, OsString},
|
||||
fs::File,
|
||||
io::Read,
|
||||
};
|
||||
|
||||
// from https://doc.rust-lang.org/std/ffi/struct.OsString.html
|
||||
fn concat_os_strings(a: &OsStr, b: &OsStr) -> OsString {
|
||||
let mut ret = OsString::with_capacity(a.len() + b.len()); // This will allocate
|
||||
ret.push(a); // This will not allocate further
|
||||
ret.push(b); // This will not allocate further
|
||||
ret
|
||||
}
|
||||
|
||||
/// Check for an environment variable named for the given key with _FILE
|
||||
/// appended to the end. If that exists, return the contents of the file, or
|
||||
/// panic if it doesn't exist. If the `"${key}_FILE"` environment variable is
|
||||
/// not set, return the value of the environment variable set by the given key,
|
||||
/// or `None` if it's not set.
|
||||
///
|
||||
/// Panics:
|
||||
/// - if the given file variable doesn't exist
|
||||
/// - if there's an error reading the specified file
|
||||
/// - if the environment variable string contains invalid unicode.
|
||||
fn get_env_var_or_file<A: AsRef<OsStr>>(key: A) -> Option<String> {
|
||||
let key = key.as_ref();
|
||||
let file_key = concat_os_strings(key, "_FILE".as_ref());
|
||||
if let Some(path) = env::var_os(file_key) {
|
||||
// open the file and read it
|
||||
let mut file = File::open(&path).unwrap_or_else(|_| panic!("no such file at {path:?}"));
|
||||
let mut val: String = default();
|
||||
file.read_to_string(&mut val)
|
||||
.unwrap_or_else(|_| panic!("reading file at {path:?}"));
|
||||
Some(val)
|
||||
} else {
|
||||
env::var_os(key).map(|val| {
|
||||
val.to_str()
|
||||
.expect(&format!("value for ${key:?} contains invalid unicode"))
|
||||
.to_string()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Connect to the database using environment variables for configuration.
|
||||
/// Panics on any failure.
|
||||
pub(crate) fn connection_url() -> String {
|
||||
let user = get_env_var_or_file("POSTGRES_USER").expect("$POSTGRES_USER");
|
||||
let password = get_env_var_or_file("POSTGRES_PASSWORD").expect("$POSTGRES_PASSWORD");
|
||||
let db = get_env_var_or_file("POSTGRES_DB").expect("$POSTGRES_DB");
|
||||
let host = get_env_var_or_file("POSTGRES_HOST").unwrap_or_else(|| "localhost".into());
|
||||
let port = get_env_var_or_file("POSTGRES_PORT")
|
||||
.map(|port| {
|
||||
port.parse::<u16>()
|
||||
.expect("$POSTGRES_PORT is not a valid port number")
|
||||
})
|
||||
.unwrap_or(5432_u16);
|
||||
format!("postgres://{user}:{password}@{host}:{port}/{db}")
|
||||
}
|
11
src/error.rs
Normal file
11
src/error.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
use derive_builder::UninitializedFieldError;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Builder(#[from] UninitializedFieldError),
|
||||
#[error(transparent)]
|
||||
SeaOrm(#[from] sea_orm::DbErr),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
11
src/main.rs
Normal file
11
src/main.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#![feature(default_free_fn)]
|
||||
mod db;
|
||||
mod error;
|
||||
use error::Result;
|
||||
use sea_orm::Database;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let db = Database::connect(db::connection_url()).await?;
|
||||
Ok(println!("Hello, world! {db:?}"))
|
||||
}
|
Loading…
Reference in a new issue