mod filter_builders;
mod flat;
mod include_arm;
mod include_validation;
mod order_arms;
mod order_catalog;
mod parse;
mod root;
mod types;
mod query_guard;
pub(crate) use flat::generate_model_path_types;
pub(crate) use include_arm::generate_relation_include_arm;
pub(crate) use include_validation::{
generate_relation_include_fields_validation_arm, generate_relation_include_path_validation_arm,
};
pub(crate) use order_arms::collect_allowed_sort_keys;
pub(crate) use order_catalog::{generate_model_order_catalog, order_catalog_ident};
pub(crate) use parse::parse_relation_attribute;
pub(crate) use query_guard::generate_relation_query_guard;
pub(crate) use root::generate_relation_root_module;
pub(crate) use types::{RelationLink, relation_link};
#[cfg(test)]
mod tests {
use cratestack_core::{Attribute, Field, SourceSpan, TypeRef};
use super::parse::{parse_relation_attribute, split_top_level};
fn span() -> SourceSpan {
SourceSpan {
start: 0,
end: 0,
line: 1,
}
}
fn field_with_relation(raw: &str) -> Field {
Field {
docs: Vec::new(),
name: "author".to_owned(),
name_span: span(),
ty: TypeRef {
name: "User".to_owned(),
name_span: span(),
arity: cratestack_core::TypeArity::Required,
generic_args: Vec::new(),
int_args: Vec::new(),
},
attributes: vec![Attribute {
raw: raw.to_owned(),
span: span(),
}],
span: span(),
}
}
#[test]
fn split_top_level_ignores_nested_brackets() {
let items = split_top_level("fields:[userId], references:[id], map:[a,b(c,d)]", ',');
assert_eq!(
items,
vec!["fields:[userId]", "references:[id]", "map:[a,b(c,d)]"]
);
}
#[test]
fn parse_relation_attribute_extracts_fields_and_references() {
let field = field_with_relation("@relation(fields:[userId], references:[id])");
let parsed = parse_relation_attribute(&field).expect("relation attribute should parse");
assert_eq!(parsed.fields, vec!["userId".to_owned()]);
assert_eq!(parsed.references, vec!["id".to_owned()]);
}
#[test]
fn parse_relation_attribute_rejects_unknown_keys() {
let field = field_with_relation("@relation(fields:[userId], ref:[id])");
assert!(parse_relation_attribute(&field).is_none());
}
#[test]
fn parse_relation_attribute_tolerates_on_delete_and_on_update() {
let field = field_with_relation(
"@relation(fields:[userId], references:[id], onDelete: Cascade, onUpdate: Restrict)",
);
let parsed = parse_relation_attribute(&field).expect("relation attribute should parse");
assert_eq!(parsed.fields, vec!["userId".to_owned()]);
assert_eq!(parsed.references, vec!["id".to_owned()]);
}
#[test]
fn parse_relation_attribute_tolerates_any_other_unrecognised_key() {
let field =
field_with_relation("@relation(fields:[userId], references:[id], futureKey: Whatever)");
let parsed = parse_relation_attribute(&field).expect("relation attribute should parse");
assert_eq!(parsed.fields, vec!["userId".to_owned()]);
assert_eq!(parsed.references, vec!["id".to_owned()]);
}
}