use std::path::PathBuf;
use crate::module::Module;
pub const DEFAULT_ROOT_DIR: &str = "./database";
pub fn setup_surql_path(folder: &str) -> PathBuf {
PathBuf::from(folder).join("setup.surql")
}
pub fn schema_dir(folder: &str) -> PathBuf {
PathBuf::from(folder).join("schema")
}
pub fn rollouts_dir(folder: &str) -> PathBuf {
PathBuf::from(folder).join("rollouts")
}
pub fn state_dir(folder: &str) -> PathBuf {
PathBuf::from(folder).join("snapshots")
}
pub fn schema_snapshot_path(folder: &str) -> PathBuf {
state_dir(folder).join("schema_snapshot.json")
}
pub fn catalog_snapshot_path(folder: &str) -> PathBuf {
state_dir(folder).join("catalog_snapshot.json")
}
pub fn tests_dir(folder: &str) -> PathBuf {
PathBuf::from(folder).join("tests")
}
pub fn suites_dir(folder: &str) -> PathBuf {
tests_dir(folder).join("suites")
}
pub fn fixtures_dir(folder: &str) -> PathBuf {
tests_dir(folder).join("fixtures")
}
pub fn seed_dir(folder: &str) -> PathBuf {
PathBuf::from(folder).join("seed")
}
pub fn seed_surql_path(folder: &str) -> PathBuf {
seed_dir(folder).join("seed.surql")
}
pub fn types_dir(folder: &str) -> PathBuf {
PathBuf::from(folder).join("types")
}
pub fn typegen_output_path(folder: &str) -> PathBuf {
types_dir(folder).join("schema.json")
}
#[derive(Debug, Clone)]
pub struct Layout {
folder: String,
module: Module,
schema_dir: Option<PathBuf>,
}
impl Layout {
pub fn new(folder: impl Into<String>, module: Module) -> Self {
Self {
folder: folder.into(),
module,
schema_dir: None,
}
}
pub fn with_schema_dir(
folder: impl Into<String>,
module: Module,
schema_dir: impl Into<PathBuf>,
) -> Self {
let folder = folder.into();
let dir = schema_dir.into();
let dir = if dir.is_absolute() {
dir
} else {
PathBuf::from(&folder).join(dir)
};
Self {
folder,
module,
schema_dir: Some(dir),
}
}
pub fn default_module(folder: impl Into<String>) -> Self {
Self::new(folder, Module::default_module())
}
pub fn folder(&self) -> &str {
&self.folder
}
pub fn module(&self) -> &Module {
&self.module
}
pub fn root(&self) -> PathBuf {
if self.module.is_default() {
PathBuf::from(&self.folder)
} else {
PathBuf::from(&self.folder).join("modules").join(self.module.name())
}
}
pub fn schema_dir(&self) -> PathBuf {
self.schema_dir.clone().unwrap_or_else(|| self.root().join("schema"))
}
pub fn rollouts_dir(&self) -> PathBuf {
self.root().join("rollouts")
}
pub fn state_dir(&self) -> PathBuf {
self.root().join("snapshots")
}
pub fn schema_snapshot_path(&self) -> PathBuf {
self.state_dir().join("schema_snapshot.json")
}
pub fn catalog_snapshot_path(&self) -> PathBuf {
self.state_dir().join("catalog_snapshot.json")
}
pub fn seed_dir(&self) -> PathBuf {
self.root().join("seed")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_module_layout_matches_the_pre_v1_paths() {
let l = Layout::default_module("./database");
assert_eq!(l.schema_dir(), schema_dir("./database"));
assert_eq!(l.rollouts_dir(), rollouts_dir("./database"));
assert_eq!(l.state_dir(), state_dir("./database"));
assert_eq!(l.schema_snapshot_path(), schema_snapshot_path("./database"));
assert_eq!(l.catalog_snapshot_path(), catalog_snapshot_path("./database"));
assert_eq!(l.seed_dir(), seed_dir("./database"));
}
#[test]
fn named_module_lives_under_modules() {
let l = Layout::new("./database", Module::new("billing").unwrap());
assert_eq!(l.root(), PathBuf::from("./database/modules/billing"));
assert_eq!(l.schema_dir(), PathBuf::from("./database/modules/billing/schema"));
assert_eq!(l.rollouts_dir(), PathBuf::from("./database/modules/billing/rollouts"));
assert_eq!(
l.schema_snapshot_path(),
PathBuf::from("./database/modules/billing/snapshots/schema_snapshot.json")
);
assert_eq!(l.seed_dir(), PathBuf::from("./database/modules/billing/seed"));
}
#[test]
fn named_module_does_not_nest_inside_the_default_schema_dir() {
let default_schema = Layout::default_module("./database").schema_dir();
let named_schema = Layout::new("./database", Module::new("billing").unwrap()).schema_dir();
assert!(
!named_schema.starts_with(&default_schema),
"{named_schema:?} must not be inside {default_schema:?}"
);
}
#[test]
fn distinct_modules_get_distinct_directories() {
let a = Layout::new("./database", Module::new("core").unwrap()).schema_dir();
let b = Layout::new("./database", Module::new("billing").unwrap()).schema_dir();
assert_ne!(a, b);
}
}